별 함수는 없다.
사용자 함수는 get_int, main 밖에 없다.
main
0x00000000004011ab <+0>: endbr64 0x00000000004011af <+4>: push rbp 0x00000000004011b0 <+5>: mov rbp,rsp 0x00000000004011b3 <+8>: sub rsp,0x20 0x00000000004011b7 <+12>: movabs rax,0x6820656c706d6953 0x00000000004011c1 <+22>: movabs rdx,0x6520796172646e61 0x00000000004011cb <+32>: mov QWORD PTR [rbp-0x20],rax 0x00000000004011cf <+36>: mov QWORD PTR [rbp-0x18],rdx 0x00000000004011d3 <+40>: mov WORD PTR [rbp-0x10],0x2178 0x00000000004011d9 <+46>: mov BYTE PTR [rbp-0xe],0x0 0x00000000004011dd <+50>: lea rax,[rip+0xe24] # 0x402008 0x00000000004011e4 <+57>: mov QWORD PTR [rbp-0x8],rax 0x00000000004011e8 <+61>: jmp 0x401237 <main+140> 0x00000000004011ea <+63>: mov eax,0x0 0x00000000004011ef <+68>: call 0x401176 <get_int> 0x00000000004011f4 <+73>: mov DWORD PTR [rbp-0xc],eax 0x00000000004011f7 <+76>: cmp DWORD PTR [rbp-0xc],0x3 0x00000000004011fb <+80>: je 0x40122d <main+130> 0x00000000004011fd <+82>: cmp DWORD PTR [rbp-0xc],0x3 0x0000000000401201 <+86>: jg 0x401237 <main+140> 0x0000000000401203 <+88>: cmp DWORD PTR [rbp-0xc],0x1 0x0000000000401207 <+92>: je 0x401211 <main+102> 0x0000000000401209 <+94>: cmp DWORD PTR [rbp-0xc],0x2 0x000000000040120d <+98>: je 0x40121f <main+116> 0x000000000040120f <+100>: jmp 0x401237 <main+140> 0x0000000000401211 <+102>: lea rax,[rbp-0x20] 0x0000000000401215 <+106>: mov rdi,rax 0x0000000000401218 <+109>: call 0x401060 <puts@plt> 0x000000000040121d <+114>: jmp 0x401237 <main+140> 0x000000000040121f <+116>: mov rax,QWORD PTR [rbp-0x8] 0x0000000000401223 <+120>: mov rdi,rax 0x0000000000401226 <+123>: call 0x401060 <puts@plt> 0x000000000040122b <+128>: jmp 0x401237 <main+140> 0x000000000040122d <+130>: mov DWORD PTR [rip+0x2e09],0x0 # 0x404040 <loop> 0x0000000000401237 <+140>: mov eax,DWORD PTR [rip+0x2e03] # 0x404040 <loop> 0x000000000040123d <+146>: test eax,eax 0x000000000040123f <+148>: jne 0x4011ea <main+63> 0x0000000000401241 <+150>: mov eax,0x0 0x0000000000401246 <+155>: leave 0x0000000000401247 <+156>: ret
get_int
0x0000000000401176 <+0>: endbr64 0x000000000040117a <+4>: push rbp 0x000000000040117b <+5>: mov rbp,rsp 0x000000000040117e <+8>: sub rsp,0x10 0x0000000000401182 <+12>: lea rax,[rbp-0x4] 0x0000000000401186 <+16>: mov rsi,rax 0x0000000000401189 <+19>: lea rax,[rip+0xe74] # 0x402004 0x0000000000401190 <+26>: mov rdi,rax 0x0000000000401193 <+29>: mov eax,0x0 0x0000000000401198 <+34>: call 0x401080 <__isoc99_scanf@plt> 0x000000000040119d <+39>: lea rax,[rbp-0x4] 0x00000000004011a1 <+43>: mov rdi,rax 0x00000000004011a4 <+46>: call 0x401070 <atoi@plt> 0x00000000004011a9 <+51>: leave 0x00000000004011aa <+52>: ret
이 코드들을 정적 분석과 동적 분석으로 캔버스로 그렸다.
함수의 흐름을 파악해보자.
일단 프롤로그 부분이다.
rax, rdx 에 문자열을 넣어주는데 [rbp-0x20],[rbp-0x18],[rbp-0x10] 에 걸쳐서 입력해 준다.
그래서 변수일거라 생각해
char string1[] = "Simple handray ex!";
라 생각했다.
그 다음에 lea로 [rbp-0x8] 에 주소가 들어가는데 처음에는 code 영역인줄 알았는데 그냥 rdata 였다.
그래서 전역으로 const char 형으로 선언해서 포인터로 넣어줬다.
const char string[] = "Hello, World"; /*global*/
const char \* hello_world = string; /*local*/
그러고 난 다음 main + 140 으로 가는데 loop 를 참조해서 반복 시킨다.
loop 는 1이고 eax 에는 1이 들어간다.
loop의 주소를 보면 이 또한 전역 변수임을 알 수 있다.
int loop = 1; /*global*/
일단 처음엔 ZF가 0이 아닌걸로 세팅 될 것 이기 떄문에 main+63으로 jmp 한다.
get_int 가 호출 될 것이고. get_int의 리턴이 [rbp-0xc] 에 들어간다.
호출하는 함수들을 보면 scanf, atoi 이다.
앞에서 get_int 의 return이 들어간다 했으니 return은 atoi 를 해주는 것 같다.
그리고 scanf의 서식 문자는 %3s 가 들어간다.
int get_int(){ char c[3]; scanf("%3s", c); return atoi(c); }
이 return 에 따라서 뒤에 호출되는 명령어가 달라지는데
cmp, je
이런식으로 돼 있는걸 보니
switch 인 것 같다.
이걸 총합하면 다음과 같다.
int c = get_int(); switch(c){ case 1: case 2: case 3: default: // 0입력시 }
1을 입력하면 Simple handray ex! 가 출력된다.
2도 Hello, Wolrd 가출력되는 것 만 빼면 구조는 비슷하다.
3을 입력하면 loop를 0으로 만드는데
그렇게 되면 eax 가 0이 되기 때문에 ZF가 0이 되어 프로그램이 종료가 된다.
모든걸 정리해보면 다음과 같이 핸드레이가 된다.
/* Never use a decompiler. Fighting! */ # include <stdio.h> # include <stdlib.h> // atoi int loop = 1; const char string[] = "Hello, Wolrd"; int get_int(){ char c[3]; scanf("%3s", c); return atoi(c); } void main(){ char string1[] = "Simple handray ex!"; const char * hello_world = string; //hello world while(loop != 0) { int c = get_int(); switch(c){ case 1: puts(string1); break; case 2: puts(hello_world); break; case 3: loop = 0; break; default: } } }
makefile 이 있어서 make로 컴파일 해줬다.
거의 똑같은거 같은데 main+140 부분에 nop 가 들어가서 먼가 다르다.
놓친 부분이 있는거 같긴한데 먼지 모르겠다.
이 글은 옵시디언을 이용해서 작성되었습니다.
'TOOR' 카테고리의 다른 글
[TOOR] 5.2 NXbit (0) | 2023.09.19 |
---|---|
[TOOR] 5.1. BOF (내 안의 버퍼가 넘친다!) (0) | 2023.09.19 |
[TOOR] 3.Stack Frame (0) | 2023.09.19 |
[TOOR] 2.Calling Convention (0) | 2023.09.19 |
[TOOR] 1.Memory Structure (0) | 2023.09.19 |