Lab1. 기본적인 디버거 사용법

2020. 10. 9. 18:16문제연습/Hitcon training

반응형

 

시스템 해킹 문제인 hitcon training을 풀어보도록 하겠습니다.

 

 

일단 파일을 열어서 보도록 하겠습니다. (명령어 : ls -al)

현재 파일 목록을 보니 실행할 수 있는 바이너리 파일과 읽을 수 있는 소스코드 파일이 있습니다.

일단 소스코드를 확인해 보도록 하겠습니다. (cat sysmagic.c)

 

 

#include <stdio.h>
#include <unistd.h>
void get_flag(){
        int fd ;
        int password;
        int magic ;
        char key[] = "Do_you_know_why_my_teammate_Orange_is_so_angry???";
        char cipher[] = {7, 59, 25, 2, 11, 16, 61, 30, 9, 8, 18, 45, 40, 89, 10, 0, 30, 22, 0, 4, 85, 22, 8, 3
1, 7, 1, 9, 0, 126, 28, 62, 10, 30, 11, 107, 4, 66, 60, 44, 91, 49, 85, 2, 30, 33, 16, 76, 30, 66};
        fd = open("/dev/urandom",0);
        read(fd,&password,4);
        printf("Give me maigc :");
        scanf("%d",&magic);
        if(password == magic){
                for(int i = 0 ; i < sizeof(cipher) ; i++){
                        printf("%c",cipher[i]^key[i]);
                }
        }
}int main(){
        setvbuf(stdout,0,2,0);
        get_flag();
        return 0 ;
}

 

 

--추가적인 정보--

setvbuf: 스트림의 버퍼링 방식과 버퍼링이 될 버퍼를 지정하는 함수.

함수에 들어가는 인자는 아래 링크를 참고할 것.

 

setvbuf 함수

setvbuf #include int setvbuf ( FILE * stream, char * buffer, int mode, size_t size ); 설명 stream의 buffering하는 방식과 buffering을 할 buffer를 지정한다. 즉, 스트림 버퍼링 방식을 변경한다. 버퍼의..

ghdwn0217.tistory.com

--풀이--

main함수에서는 setvbuf를 호출후 바로 get_flag라는 함수를 호출하고 있습니다.

get_flag함수 내부에서 주목해야 하는 부분은 아래 코드입니다.

 

내부 소스코드에 의하면, 파일로부터 읽어온 password가 사용자가 입력한 magic값과 일치하면 key^cipher한 숨겨진 flag를 출력한 것으로 보입니다.

 

그러나 /dev/urandom 내부 내용을 알 수 없으므로 프로그램을 실행시킨 후에 printf()가 call되는 지점에 중단점을 걸고 password값이 저장되는 부분을 확인하여 magic에 입력하면 flag가 출력될 것으로 보입니다.

(이제 여기서 gdb 디버거가 활용됩니다.)

 

disas get_flag

0x0804859b <+0>: push ebp

0x0804859c <+1>: mov ebp,esp ----------------------------------- 함수의 스택 프레임 형성

0x0804859e <+3>: sub esp,0x88 -------------------------------- 스택 공간 확보 작업

0x080485a4 <+9>: mov eax,gs:0x14

0x080485aa <+15>: mov DWORD PTR [ebp-0xc],eax

0x080485ad <+18>: xor eax,eax

0x080485af <+20>: mov DWORD PTR [ebp-0x3e],0x795f6f44

0x080485b6 <+27>: mov DWORD PTR [ebp-0x3a],0x6b5f756f

0x080485bd <+34>: mov DWORD PTR [ebp-0x36],0x5f776f6e

0x080485c4 <+41>: mov DWORD PTR [ebp-0x32],0x5f796877

0x080485cb <+48>: mov DWORD PTR [ebp-0x2e],0x745f796d

0x080485d2 <+55>: mov DWORD PTR [ebp-0x2a],0x6d6d6165

0x080485d9 <+62>: mov DWORD PTR [ebp-0x26],0x5f657461

0x080485e0 <+69>: mov DWORD PTR [ebp-0x22],0x6e61724f

0x080485e7 <+76>: mov DWORD PTR [ebp-0x1e],0x695f6567

0x080485ee <+83>: mov DWORD PTR [ebp-0x1a],0x6f735f73

0x080485f5 <+90>: mov DWORD PTR [ebp-0x16],0x676e615f

0x080485fc <+97>: mov DWORD PTR [ebp-0x12],0x3f3f7972 --------- char key[]

0x08048603 <+104>: mov WORD PTR [ebp-0xe],0x3f

0x08048609 <+110>: mov BYTE PTR [ebp-0x6f],0x7

0x0804860d <+114>: mov BYTE PTR [ebp-0x6e],0x3b

0x08048611 <+118>: mov BYTE PTR [ebp-0x6d],0x19

0x08048615 <+122>: mov BYTE PTR [ebp-0x6c],0x2

0x08048619 <+126>: mov BYTE PTR [ebp-0x6b],0xb

0x0804861d <+130>: mov BYTE PTR [ebp-0x6a],0x10

0x08048621 <+134>: mov BYTE PTR [ebp-0x69],0x3d

0x08048625 <+138>: mov BYTE PTR [ebp-0x68],0x1e

0x08048629 <+142>: mov BYTE PTR [ebp-0x67],0x9

0x0804862d <+146>: mov BYTE PTR [ebp-0x66],0x8

0x08048631 <+150>: mov BYTE PTR [ebp-0x65],0x12

0x08048635 <+154>: mov BYTE PTR [ebp-0x64],0x2d

0x08048639 <+158>: mov BYTE PTR [ebp-0x63],0x28

0x0804863d <+162>: mov BYTE PTR [ebp-0x62],0x59

0x08048641 <+166>: mov BYTE PTR [ebp-0x61],0xa

0x08048645 <+170>: mov BYTE PTR [ebp-0x60],0x0

0x08048649 <+174>: mov BYTE PTR [ebp-0x5f],0x1e

0x0804864d <+178>: mov BYTE PTR [ebp-0x5e],0x16

0x08048651 <+182>: mov BYTE PTR [ebp-0x5d],0x0

0x08048655 <+186>: mov BYTE PTR [ebp-0x5c],0x4

0x08048659 <+190>: mov BYTE PTR [ebp-0x5b],0x55

0x0804865d <+194>: mov BYTE PTR [ebp-0x5a],0x16

0x08048661 <+198>: mov BYTE PTR [ebp-0x59],0x8

0x08048665 <+202>: mov BYTE PTR [ebp-0x58],0x1f

0x08048669 <+206>: mov BYTE PTR [ebp-0x57],0x7

0x0804866d <+210>: mov BYTE PTR [ebp-0x56],0x1

0x08048671 <+214>: mov BYTE PTR [ebp-0x55],0x9

0x08048675 <+218>: mov BYTE PTR [ebp-0x54],0x0

0x08048679 <+222>: mov BYTE PTR [ebp-0x53],0x7e

0x0804867d <+226>: mov BYTE PTR [ebp-0x52],0x1c

0x08048681 <+230>: mov BYTE PTR [ebp-0x51],0x3e

0x08048685 <+234>: mov BYTE PTR [ebp-0x50],0xa

0x08048689 <+238>: mov BYTE PTR [ebp-0x4f],0x1e

0x0804868d <+242>: mov BYTE PTR [ebp-0x4e],0xb

0x08048691 <+246>: mov BYTE PTR [ebp-0x4d],0x6b

0x08048695 <+250>: mov BYTE PTR [ebp-0x4c],0x4

0x08048699 <+254>: mov BYTE PTR [ebp-0x4b],0x42

0x0804869d <+258>: mov BYTE PTR [ebp-0x4a],0x3c

0x080486a1 <+262>: mov BYTE PTR [ebp-0x49],0x2c

0x080486a5 <+266>: mov BYTE PTR [ebp-0x48],0x5b

0x080486a9 <+270>: mov BYTE PTR [ebp-0x47],0x31

0x080486ad <+274>: mov BYTE PTR [ebp-0x46],0x55

0x080486b1 <+278>: mov BYTE PTR [ebp-0x45],0x2

0x080486b5 <+282>: mov BYTE PTR [ebp-0x44],0x1e

0x080486b9 <+286>: mov BYTE PTR [ebp-0x43],0x21

0x080486bd <+290>: mov BYTE PTR [ebp-0x42],0x10

0x080486c1 <+294>: mov BYTE PTR [ebp-0x41],0x4c

0x080486c5 <+298>: mov BYTE PTR [ebp-0x40],0x1e

0x080486c9 <+302>: mov BYTE PTR [ebp-0x3f],0x42 --------- char cipher[]

0x080486cd <+306>: sub esp,0x8

0x080486d0 <+309>: push 0x0 ---- open 함수 인자 ( 0 )

0x080486d2 <+311>: push 0x8048830 ---- open 함수 인자 ( "/dev/urandom" )

0x080486d7 <+316>: call 0x8048440 <open@plt>

0x080486dc <+321>: add esp,0x10

0x080486df <+324>: mov DWORD PTR [ebp-0x74],eax

0x080486e2 <+327>: sub esp,0x4

0x080486e5 <+330>: push 0x4

0x080486e7 <+332>: lea eax,[ebp-0x80]

0x080486ea <+335>: push eax

0x080486eb <+336>: push DWORD PTR [ebp-0x74] ---- read 함수 인자 (&password),

0x080486ee <+339>: call 0x8048410 <read@plt>

0x080486f3 <+344>: add esp,0x10

0x080486f6 <+347>: sub esp,0xc

0x080486f9 <+350>: push 0x804883d

0x080486fe <+355>: call 0x8048420 <printf@plt>

0x08048703 <+360>: add esp,0x10

0x08048706 <+363>: sub esp,0x8

0x08048709 <+366>: lea eax,[ebp-0x7c]

0x0804870c <+369>: push eax

0x0804870d <+370>: push 0x804884d ---- int형 변수 magic 주소

0x08048712 <+375>: call 0x8048480 <__isoc99_scanf@plt> /// 중단점 설정 지점

0x08048717 <+380>: add esp,0x10

0x0804871a <+383>: mov edx,DWORD PTR [ebp-0x80] ---- password가 위치한 것으로 추정되는 위치

0x0804871d <+386>: mov eax,DWORD PTR [ebp-0x7c]

0x08048720 <+389>: cmp edx,eax ----- if(password == magic)

0x08048722 <+391>: jne 0x8048760 <get_flag+453>

0x08048724 <+393>: mov DWORD PTR [ebp-0x78],0x0

0x0804872b <+400>: jmp 0x8048758 <get_flag+445>

0x0804872d <+402>: lea edx,[ebp-0x6f]

0x08048730 <+405>: mov eax,DWORD PTR [ebp-0x78]

0x08048733 <+408>: add eax,edx

0x08048735 <+410>: movzx ecx,BYTE PTR [eax]

0x08048738 <+413>: lea edx,[ebp-0x3e]

0x0804873b <+416>: mov eax,DWORD PTR [ebp-0x78]

0x0804873e <+419>: add eax,edx

0x08048740 <+421>: movzx eax,BYTE PTR [eax]

0x08048743 <+424>: xor eax,ecx

0x08048745 <+426>: movsx eax,al

0x08048748 <+429>: sub esp,0xc

0x0804874b <+432>: push eax

0x0804874c <+433>: call 0x8048470 <putchar@plt>

0x08048751 <+438>: add esp,0x10

0x08048754 <+441>: add DWORD PTR [ebp-0x78],0x1

0x08048758 <+445>: mov eax,DWORD PTR [ebp-0x78]

0x0804875b <+448>: cmp eax,0x30

0x0804875e <+451>: jbe 0x804872d <get_flag+402>

0x08048760 <+453>: nop

0x08048761 <+454>: mov eax,DWORD PTR [ebp-0xc]

0x08048764 <+457>: xor eax,DWORD PTR gs:0x14

0x0804876b <+464>: je 0x8048772 <get_flag+471>

0x0804876d <+466>: call 0x8048430 <__stack_chk_fail@plt>

0x08048772 <+471>: leave

0x08048773 <+472>: ret

전략을 알리자면 edx,eax ----- if(password == magic) 에 중단점을 걸고 scanf 함수의 return 값인 eax의 값을 edx와 같은 값으로 수정하여 플래그를 출력하도록 하였습니다.

 

결과적으로 우리가 원하는 플래그를 출력하였습니다.

 

제가 푼 방식은 실행 파일이 scanf 함수입력받고 if 문으로 비교하는 지점에 중단점을 걸어 레지스터 값을 조작하여 flag를 출력하였습니다.

물론 이 방법 말고 char key[], char cipher[] 배열을 이용하여 전수 조사를 하거나 if문에 해당하는 어셈블리 코드의 흐름 분기를 무조건 점프(jmp)로 수정해도 풀립니다.

 

이번 문제를 통해 gdb 디버거의 전반적인 사용법을 익히길 바랍니다.

 

반응형

'문제연습 > Hitcon training' 카테고리의 다른 글

Lab7. Format String Bug (진행 중)  (0) 2020.12.15
Lab6. Fake ebp, stack pivot (진행 중)  (0) 2020.12.13
Lab5. Return Oriented Programming  (0) 2020.12.09
Lab4. Return To Libc  (0) 2020.12.09
Lab3. 오버플로 공격 기초  (0) 2020.12.05