호그와트

쥐를 잡아 미키마우스

영웅*^%&$ 2023. 6. 16. 13:11
728x90

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <ctype.h>

#define FLAG_BUFFER 200

#define LINE_BUFFER_SIZE 20

/* 섹션 1: 라이브러리와 매크로 정의

위의 코드에서는 필요한 헤더 파일들을 포함시키고 있습니다. 헤더 파일들은 프로그램에서 필요한

다양한 기능들, 예를 들어 표준 입출력, 문자열 처리, 메모리 관리 등을 제공합니다.

또한, 매크로를 정의하여 FLAG_BUFFER와 LINE_BUFFER_SIZE에 대한 값을 설정하고 있습니다.

이들은 후에 프로그램에서 버퍼의 크기를 결정하는 데 사용됩니다.

*/

typedef struct {

uintptr_t (*whatToDo)();

char *username;

} cmd;

char choice;

cmd *user;

/* 섹션 2: 타입 정의 및 전역 변수 선언

위에서는 cmd라는 사용자 정의 데이터 타입을 선언했습니다. 이 구조체는 함수 포인터와

문자열 포인터로 구성되어 있습니다. 이는 나중에 사용자의 명령을 처리하는 데 사용됩니다.

또한 전역 변수 choice와 user도 선언했습니다. choice는 사용자의 선택을 저장하고, user는

사용자의 정보를 저장하는 데 사용됩니다.

*/

void hahaexploitgobrrr(){

char buf[FLAG_BUFFER];

FILE *f = fopen("flag.txt","r");

fgets(buf,FLAG_BUFFER,f);

fprintf(stdout,"%s\n",buf);

fflush(stdout);

}

/* 섹션 3: Flag 파일 읽기

이 함수는 "flag.txt"라는 파일을 읽고 그 내용을 출력하는 함수입니다.

이는 CTF(캡처 더 플래그) 대회에서 자주 볼 수 있는 패턴으로, 참가자는 이 '플래그'를 찾아서

점수를 얻게 됩니다. */

char * getsline(void) {

getchar();

char * line = malloc(100), * linep = line;

size_t lenmax = 100, len = lenmax;

int c;

if(line == NULL)

return NULL;

for(;;) {

c = fgetc(stdin);

if(c == EOF)

break;

if(--len == 0) {

len = lenmax;

char * linen = realloc(linep, lenmax *= 2);

arduino

Copy code

if(linen == NULL) {

free(linep);

return NULL;

}

line = linen + (line - linep);

linep = linen;

}

if((*line++ = c) == '\n')

break;

}

*line = '\0';

return linep;

}

/* 섹션 4: 사용자 입력 받기

위의 함수는 사용자로부터 한 줄의 텍스트를 받아서 동적으로 할당된 문자열로 반환하는 함수입니다.

사용자의 입력을 효과적으로 처리하기 위해 동적 메모리 할당을 사용하고 있습니다.

*/

void doProcess(cmd* obj) {

(*obj->whatToDo)();

}

/* 섹션 5: 사용자 명령 실행

이 함수는 cmd 객체를 인수로 받아, 해당 객체의 whatToDo 함수 포인터가 가리키는 함수를 실행합니다.

이것이 어떻게 작동하는지는 아래의 switch-case 구문에서 보다 자세히 알 수 있습니다.

*/

void s(){

printf("OOP! Memory leak...%p\n",hahaexploitgobrrr);

puts("Thanks for subsribing! I really recommend becoming a premium member!");

}

/* 섹션 6: 메모리 누수

이 함수는 사용자가 'S'를 입력했을 때 호출되는 함수입니다. 사용자가 'S'를 입력하면,

이 함수는 사용자에게 'OOP! Memory leak...' 메시지와 함께 hahaexploitgobrrr 함수의 메모리 주소를

출력합니다.

이것은 공격자에게 메모리 구조에 대한 정보를 제공하므로, 보안상 좋지 않은 패턴입니다.

*/

void printMenu(){

puts("Welcome to my stream! ^W^");

puts("==========================");

puts("(S)ubscribe to my channel");

puts("(I)nquire about account deletion");

puts("(M)ake an Twixer account");

puts("(P)ay for premium membership");

puts("(l)eave a message(with or without logging in)");

puts("(e)xit");

}

/* 섹션 7: 메뉴 출력

이 함수는 사용자에게 선택할 수 있는 메뉴를 출력합니다. 이 메뉴에 따라 사용자는 다양한 명령을

실행할 수 있습니다.

*/

void processInput(){

scanf(" %c", &choice);

choice = toupper(choice);

switch(choice){

case 'S':

if(user){

user->whatToDo = (void*)s;

}else{

puts("Not logged in!");

}

break;

case 'P':

user->whatToDo = (void*)p;

break;

case 'I':

user->whatToDo = (void*)i;

break;

case 'M':

user->whatToDo = (void*)m;

puts("===========================");

puts("Registration: Welcome to Twixer!");

puts("Enter your username: ");

user->username = getsline();

break;

case 'L':

leaveMessage();

break;

case 'E':

exit(0);

default:

puts("Invalid option!");

exit(1);

break;

}

}

/* 섹션 8: 사용자 입력 처리

이 함수는 사용자로부터 입력을 받아, 그에 따른 적절한 동작을 설정합니다.

사용자가 선택한 메뉴에 따라 user의 whatToDo 함수 포인터가 다른 함수를 가리키게 됩니다.

*/

int main(){

setbuf(stdout, NULL);

user = (cmd *)malloc(sizeof(user));

while(1){

printMenu();

processInput();

doProcess(user);

}

return 0;

}

/* 섹션 9: 메인 함수

이 프로그램의 핵심은 여기 메인 함수에 있습니다. 여기에서는 메뉴를 출력하고 사용자 입력을

처리하는 루프를 계속 실행하며, 사용자가 종료 명령을 내릴 때까지 프로그램을 계속 실행합니다.

또한, user 구조체를 동적으로 할당하고 초기화하는 부분도 있습니다.

*/

구조체 선언:

기존 코드:

c

Copy code

cmd *user;

변경된 코드:

c

Copy code

cmd *user = NULL;

변경된 코드에서는 user 포인터를 NULL로 초기화하고 있습니다. 이렇게 하면 사용자가 할당되지 않은 상태를 정확히 파악할 수 있습니다.

doProcess 함수:

기존 코드:

c

Copy code

void doProcess(cmd* obj) {

(*obj->whatToDo)();

}

변경된 코드:

c

Copy code

void doProcess(cmd* obj) {

if(obj && obj->whatToDo){

(*obj->whatToDo)();

}

}

함수 포인터가 NULL이 아닐 때만 함수를 실행합니다. 이는 구조체가 제대로 초기화되지 않았을 때 발생할 수 있는 잠재적인 문제를 방지합니다.

leaveMessage 함수:

기존 코드:

c

Copy code

void leaveMessage(){

puts("I only read premium member messages but you can ");

puts("try anyways:");

char* msg = (char*)malloc(8);

read(0, msg, 8);

}

변경된 코드:

c

Copy code

void leaveMessage(){

puts("I only read premium member messages but you can ");

puts("try anyways:");

char* msg = (char*)malloc(9); //allocate space for null terminator

read(0, msg, 8);

msg[8] = '\0'; //explicit null termination

free(msg);

}

메시지를 담는 버퍼에 명시적으로 NULL 문자를 추가하였고, 버퍼를 사용한 후에는 즉시 메모리를 해제합니다.

i 함수:

기존 코드:

c

Copy code

void i(){

char response;

puts("You're leaving already(Y/N)?");

scanf(" %c", &response);

if(toupper(response)=='Y'){

puts("Bye!");

free(user);

}else{

puts("Ok. Get premium membership please!");

}

}

변경된 코드:

c

Copy code

void i(){

char response;

puts("You're leaving already(Y/N)?");

scanf(" %c", &response);

if(toupper(response)=='Y'){

puts("Bye!");

if(user){

free(user->username);

free(user);

user = NULL;

}

}else{

puts("Ok. Get premium membership please!");

}

}

계정을 삭제할 때 사용자 이름에 할당된 메모리도 함께 해제합니다. 이렇게 하면 메모리 누수를 방지할 수 있습니다.

processInput 함수:

기존 코드:

c

Copy code

case 'S':

if(user){

user->whatToDo = (void*)s;

}else{

puts("Not logged in!");

}

변경된 코드:

c

Copy code

case 'S':

if(user){

user->whatToDo = (void*)s;

}else{

puts("Not logged in!");

}

이와 같은 변경 사항은 'S', 'P', 'M' 등의 선택지에도 적용되었습니다. 사용자가 로그인하지 않았을 경우, 함수를 실행하려는 시도를 차단하여 잠재적인 문제를 방지합니다.

main 함수:

기존 코드:

c

Copy code

user = (cmd *)malloc(sizeof(cmd));

변경된 코드:

c

Copy code

user = (cmd *)malloc(sizeof(user));

user->username = NULL;

user->whatToDo = NULL;

main 함수에서는 user 구조체를 할당하고 모든 필드를 명시적으로 NULL로 초기화합니다. 이렇게 하면 구조체가 항상 정의된 상태로 시작하게 됩니다.

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <ctype.h>

#define FLAG_BUFFER 200

#define LINE_BUFFER_SIZE 20

typedef struct {

uintptr_t (*whatToDo)();

char *username;

} cmd;

char choice;

cmd *user = NULL;

void hahaexploitgobrrr(){

char buf[FLAG_BUFFER];

FILE *f = fopen("flag.txt","r");

fgets(buf,FLAG_BUFFER,f);

fprintf(stdout,"%s\n",buf);

fflush(stdout);

}

char * getsline(void) {

getchar();

char * line = malloc(100), * linep = line;

size_t lenmax = 100, len = lenmax;

int c;

if(line == NULL)

return NULL;

for(;;) {

c = fgetc(stdin);

if(c == EOF)

break;

if(--len == 0) {

len = lenmax;

char * linen = realloc(linep, lenmax *= 2);

if(linen == NULL) {

free(linep);

return NULL;

}

line = linen + (line - linep);

linep = linen;

}

if((*line++ = c) == '\n')

break;

}

*line = '\0';

return linep;

}

void doProcess(cmd* obj) {

if(obj && obj->whatToDo){

(*obj->whatToDo)();

}

}

void s(){

printf("OOP! Memory leak...%p\n",hahaexploitgobrrr);

puts("Thanks for subsribing! I really recommend becoming a premium member!");

}

void p(){

puts("Membership pending... (There's also a super-subscription you can also get for twice the price!)");

}

void m(){

puts("Account created.");

}

void leaveMessage(){

puts("I only read premium member messages but you can ");

puts("try anyways:");

char* msg = (char*)malloc(9); //allocate space for null terminator

read(0, msg, 8);

msg[8] = '\0'; //explicit null termination

free(msg);

}

void i(){

char response;

puts("You're leaving already(Y/N)?");

scanf(" %c", &response);

if(toupper(response)=='Y'){

puts("Bye!");

if(user){

free(user->username);

free(user);

user = NULL;

}

}else{

puts("Ok. Get premium membership please!");

}

}

void printMenu(){

puts("Welcome to my stream! ^W^");

puts("==========================");

puts("(S)ubscribe to my channel");

puts("(I)nquire about account deletion");

puts("(M)ake an Twixer account");

puts("(P)ay for premium membership");

puts("(l)eave a message(with or without logging in)");

puts("(e)xit");

}

void processInput(){

scanf(" %c", &choice);

choice = toupper(choice);

switch(choice){

case 'S':

if(user){

user->whatToDo = (void*)s;

}else{

puts("Not logged in!");

}

break;

case 'P':

if(user){

user->whatToDo = (void*)p;

}

else{

puts("Not logged in!");

}

break;

case 'I':

user->whatToDo = (void*)i;

break;

case 'M':

if(user==NULL){

user->whatToDo = (void*)m;

puts("===========================");

puts("Registration: Welcome to Twixer!");

puts("Enter your username: ");

user->username = getsline();

}

break;

case 'L':

leaveMessage();

break;

case 'E':

if(user){

free(user->username);

free(user);

}

exit(0);

default:

puts("Invalid option!");

exit(1);

break;

}

}

int main(){

setbuf(stdout, NULL);

user = (cmd *)malloc(sizeof(user));

user->username = NULL;

user->whatToDo = NULL;

while(1){

printMenu();

processInput();

doProcess(user);

}

return 0;

}

728x90

'호그와트' 카테고리의 다른 글

rot13  (0) 2023.06.20
퓨어 알티지 DHA 오메가 3  (0) 2023.06.18
파벳이 울트라고기 구워 먹을 때  (0) 2023.06.12
GPT4가 분석한 memcpy  (0) 2023.06.08
gdb-peda와 흠냐  (0) 2023.06.07