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;
}