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: 스트림의 버퍼링 방식과 버퍼링이 될 버퍼를 지정하는 함수.
함수에 들어가는 인자는 아래 링크를 참고할 것.
--풀이--
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 |