TOOR

[TOOR] 4.Handray

lmxx 2023. 9. 19. 12:38
728x90
반응형

별 함수는 없다.
사용자 함수는 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 가 들어가서 먼가 다르다.
놓친 부분이 있는거 같긴한데 먼지 모르겠다.

이 글은 옵시디언을 이용해서 작성되었습니다.

728x90
반응형