카테고리 없음

리버싱 3차시

sjong 2023. 7. 3. 10:41

1. prob0

.text:0000000000001189 ; int __fastcall main(int argc, const char **argv, const char **envp)
.text:0000000000001189                 public main
.text:0000000000001189 main            proc near               ; DATA XREF: _start+21↑o
.text:0000000000001189
.text:0000000000001189 var_12          = byte ptr -12h
.text:0000000000001189 var_8           = qword ptr -8
.text:0000000000001189
.text:0000000000001189 ; __unwind {
.text:0000000000001189                 endbr64

여기서 int __fastcall main(int argc, const char **argv, const char **envp) 을 보아 main의 형태를 볼 수 있다.

int __fastcall main(int argc, const char **argv, const char **envp){

	return 0;
}

그리고 char형태의 var_12와 var_8 변수를 확인 가능하다.

.text:000000000000118D                 push    rbp
.text:000000000000118E                 mov     rbp, rsp
.text:0000000000001191                 sub     rsp, 20h
.text:0000000000001195                 mov     rax, fs:28h
.text:000000000000119E                 mov     [rbp+var_8], rax
.text:00000000000011A2                 xor     eax, eax
.text:00000000000011A4                 lea     rax, [rbp+var_12]
.text:00000000000011A8                 mov     rsi, rax
.text:00000000000011AB                 lea     rdi, a10s       ; "%10s"
.text:00000000000011B2                 mov     eax, 0
.text:00000000000011B7                 call    ___isoc99_scanf

아래에 call    ___isoc99_scanf 로 호출하는 것을 확인 가능하고 #include <stdio.h>도 써줘야 한다.

그리고 %10s를 실행하려면 var_12는 최소 10바이트 이상이고 위에서 -12h로 12바이트라는 걸 유추 가능하다.

#include <stdio.h>

int __fastcall main(int argc, const char **argv, const char **envp){
	char var[12];
	scanf("%10s", var_12);
	return 0;
}
.text:00000000000011BC                 lea     rax, [rbp+var_12]
.text:00000000000011C0                 mov     rsi, rax
.text:00000000000011C3                 lea     rdi, format     ; "%s"
.text:00000000000011CA                 mov     eax, 0
.text:00000000000011CF                 call    _printf

마지막으로는 printf와 %s를 보아 printf가 호출된 것으로 확인 가능하다.

#include <stdio.h>

int __fastcall main(int argc, const char **argv, const char **envp){
	char var[12];
	scanf("%10s", var_12);
	printf("%s", var_12);
    
	return 0;
}


2. prob1

 

.text:0000000000001149 ; int __fastcall main(int argc, const char **argv, const char **envp)
.text:0000000000001149                 public main
.text:0000000000001149 main            proc near               ; DATA XREF: _start+21↑o
.text:0000000000001149
.text:0000000000001149 var_4           = dword ptr -4
.text:0000000000001149
.text:0000000000001149 ; __unwind {

prob0과는 다르게 var_4가 int형인 모습이다.

먼저 main의 형태는 확인했으니 c로 바꿔주겠다.

int __fastcall main(int argc, const char **argv, const char **envp){

}
.text:0000000000001149                 endbr64
.text:000000000000114D                 push    rbp
.text:000000000000114E                 mov     rbp, rsp
.text:0000000000001151                 sub     rsp, 10h
.text:0000000000001155                 mov     [rbp+var_4], 0
.text:000000000000115C                 jmp     short loc_1173
.text:000000000000115E ; ---------------------------------------------------------------------------
.text:000000000000115E
.text:000000000000115E loc_115E:                               ; CODE XREF: main+2E↓j
.text:000000000000115E                 lea     rdi, format     ; "hello world"
.text:0000000000001165                 mov     eax, 0
.text:000000000000116A                 call    _printf
.text:000000000000116F                 add     [rbp+var_4], 1
.text:0000000000001173
.text:0000000000001173 loc_1173:                               ; CODE XREF: main+13↑j
.text:0000000000001173                 cmp     [rbp+var_4], 9
.text:0000000000001177                 jle     short loc_115E
.text:0000000000001179                 mov     eax, 0
.text:000000000000117E                 leave
.text:000000000000117F                 retn

 

먼저 jmp가 있는데 아래에 cmp도 보인다.

jle는 왼쪽 인자가 오른쪽 인자보다 작으면 점프하는 명령어이다.

처음엔 rsp에 10을 빼고 var_4에 0을 mov한다.

그다음 cmp로 비교를 하고 "hello world"를 출력한다.

그리고 add로 var_4에 1을 계속 더 해주고, cmp로 var_4가 9보다 크면 종료한다.

구성으로 보면 for문인 것을 확인할 수 있다. 조건이 참이면 왼쪽을 계속 실행하고 조건에 맞지 않거나 반복이 끝나면 오른쪽을 실행한다.

#include <stdio.h>

int __fastcall main(int argc, const char **argv, const char **envp) {
  int var_4;
  for (var_4 = 0; var_4 <= 9; var_4++) {
  	printf("hello world");
  }
  
  return 0;
}


3. prob2

.text:0000000000001189 ; int __fastcall main(int argc, const char **argv, const char **envp)
.text:0000000000001189                 public main
.text:0000000000001189 main            proc near               ; DATA XREF: _start+21↑o
.text:0000000000001189
.text:0000000000001189 var_10          = dword ptr -10h
.text:0000000000001189 var_C           = dword ptr -0Ch
.text:0000000000001189 var_8           = qword ptr -8
.text:0000000000001189
.text:0000000000001189 ; __unwind {

이번에도 main의 형태는 같고 int형 변수 var_10, var_C와 unsigned __int64형 변수 var_8이 선언됐다.

int __fastcall main(int argc, const char **argv, const char **envp){

}
.text:0000000000001189                 endbr64
.text:000000000000118D                 push    rbp
.text:000000000000118E                 mov     rbp, rsp
.text:0000000000001191                 sub     rsp, 10h
.text:0000000000001195                 mov     rax, fs:28h
.text:000000000000119E                 mov     [rbp+var_8], rax
.text:00000000000011A2                 xor     eax, eax
.text:00000000000011A4                 mov     [rbp+var_10], 0
.text:00000000000011AB                 lea     rax, [rbp+var_10]
.text:00000000000011AF                 mov     rsi, rax
.text:00000000000011B2                 lea     rdi, format     ; "%d"
.text:00000000000011B9                 mov     eax, 0
.text:00000000000011BE                 call    ___isoc99_scanf
.text:00000000000011C3                 mov     [rbp+var_C], 0
.text:00000000000011CA                 jmp     short loc_11EA
.text:00000000000011CC ; ---------------------------------------------------------------------------
.text:00000000000011CC
.text:00000000000011CC loc_11CC:                               ; CODE XREF: main+65↓j
.text:00000000000011CC                 mov     eax, [rbp+var_10]
.text:00000000000011CF                 imul    eax, [rbp+var_C]
.text:00000000000011D3                 mov     esi, eax
.text:00000000000011D5                 lea     rdi, format     ; "%d"
.text:00000000000011DC                 mov     eax, 0
.text:00000000000011E1                 call    _printf
.text:00000000000011E6                 add     [rbp+var_C], 1
.text:00000000000011EA
.text:00000000000011EA loc_11EA:                               ; CODE XREF: main+41↑j
.text:00000000000011EA                 cmp     [rbp+var_C], 13h
.text:00000000000011EE                 jle     short loc_11CC
.text:00000000000011F0                 mov     eax, 0
.text:00000000000011F5                 mov     rdx, [rbp+var_8]
.text:00000000000011F9                 xor     rdx, fs:28h
.text:0000000000001202                 jz      short locret_1209
.text:0000000000001204                 call    ___stack_chk_fail
.text:0000000000001209
.text:0000000000001209 locret_1209:                            ; CODE XREF: main+79↑j
.text:0000000000001209                 leave
.text:000000000000120A                 retn

이번에도 rsp를 10만큼 뺴주고 [rbp+var_8]에 rax를 넣는다.

xor로 eax와 eax를 비교하고 [rbp+var_10]에 0을 넣는다. [rbp+var_10]의 주소값을 rax에 넣고 마지막으로 rax를 rsi에 넣고 %d문자열을 scanf로 불러온다. 이번에도 반복문이 있는데  cmp [rbp+var_C], 13h에서 13h는 hex코드, 즉 16진수를 의미하며 19보다 같거나 작을 동안 printf를 실행한다. 그리고 mov로 eax에 var_10 값을 넣고 imul로 var_10과 var_C를 곱한 값을 printf하는 것 같다.

#include <stdio.h>

int __fastcall main(int argc, const char **argv, const char **envp) {
   int var_10, var_C;
   unsigned __int64 var_8;
   var_10 = 0;
   
   for(var_10 = 0; var_10 <= 19; var_10++){
   	printf("%d", var_10 * var_C);
   }
   
   return 0;
}