이번 포스팅은 아래 c언어로 작성된 소스코드를 토대로 만들어진 exe(실행 파일)을 x64dbg 분석 툴을 이용해서 분석하는 것을 목표로 합니다.
#include <stdio.h >
int main()
{
int a, b, c, d;
a = 22;
b = 5;
c = a + b;
d = a - b;
printf("a = %d\nb = %d\nc = %d\nd = %d", a, b, c, d);
}
주요 분석 부분의 메모리 주소는 다음과 같습니다.
메모리주소 | 어셈블리코드 | 주석(설명) |
00401003 | sub esp,10 | 변수가 4개 |
00401006 | mov dword ptr ss:[ebp-4], 16 | ebp-4 a=(22) |
0040100D | mov dword ptr ss:[ebp-8], 5 | ebp-8 b=(5) |
00401014 | mov eax,dword ptr ss:[ebp-4] | eax=(22) |
00401017 | add eax,dword ptr ss:[ebp-8] | eax=(22) + (5) = eax = (a) + (b) |
0040101A | mov dword ptr ss:[ebp-10], eax | ebp-10=1B(27) c=(a) + (b) |
0040101D | mov ecx, dword ptr ss:[ebp-4] | ecx= (a)= 22 |
00401020 | sub ecx, dword ptr ss:[ebp-8] | ecx = (a) - (b) (22)-(5) |
00401023 | mov dword ptr ss:[ebp-C], ecx | ebp-C = (a) - (b) 11(17) |
00401026 | mov edx, dword ptr ss:[ebp-C] | edx d=(a) - (b) = (17) |
한 줄 한 줄 살펴보겠습니다.
00401003 | sub esp,10 | 변수가 4개 |
sub esp,10를 통해 소스코드에서 변수가 4개임을 유추할 수 있다고 설명란에 적었습니다.
일단 어셈블리 코드 란에서의 10은 16진수기 때문에 10진수로 변환하면 '16'이 된다는 점을 알아야 합니다.
16 진수 '10' -> 10진수 '16'
sub는 빼기 명령어고, 'esp값에서 16을 뺀다'라는 의미입니다.
esp를 16byte만큼 빼주며 스택 공간을 확보합니다. 함수의 로컬(지역) 변수는 스택에 저장되며, 선언할 변수는 int 타입이므로 4byte입니다. 즉, 4byte x 4개의 변수 ->16byte 로 추정할 수 있게 됩니다.
4byte의 변수 네 개를 스택에 저장해야 하기 때문에 16byte가 필요함으로 16byte의 공간을 빼서 네 개의 변수에게 필요한 메모리 공간을 확보해두는 의미입니다.
00401006 | mov dword ptr ss:[ebp-4], 16 | ebp-4 a=(22) |
지역변수는 "ss:[주소]"로 표현하고,
전역변수는 "ds:[주소]"로 표현합니다.
mov는 목적지로 값을 넣을 때 사용합니다.
즉 해당 라인은 16진수의 '16'(10진수->'22')이라는 값을 [ebp-4]라는 주소에 저장하겠다는 의미입니다.
지역변수 a에 22라는 값을 저장하는 라인이라고 추정할 수 있습니다.
0040100D | mov dword ptr ss:[ebp-8], 5 | ebp-8 b=(5) |
위와 같은 방식으로 예측했을 때 해당 라인은
16진수의 '5'(10진수 -> '5')라는 값을 [ebp-8]라는 주소에 저장하겠다는 의미입니다.
지역변수 b에 5라는 값을 저장하는 라인이라고 추정할 수 있습니다.
00401014 | mov eax,dword ptr ss:[ebp-4] | eax=(22) |
위와 같은 형태는 mov eax,[esp] 형태인데, '주소[esp] 안의 값을 읽어와 eax에 저장함' 라고 설명할 수 있습니다.
이와 같은 방식으로 예측했을 때 해당 라인은
주소 [ebp-4]에 저장된 값을 읽어와 eax에 저장한다는 의미입니다.
00401017 | add eax,dword ptr ss:[ebp-8] | eax=(22) + (5) = eax = (a) + (b) |
add는 산술연산 명령어입니다. 해당 라인은
저장된 eax에 주소 [ebp-8]에 저장된 값을 더한다는 의미입니다.
주소 [ebp-4]는 변수 a에 22라는 값을 저장했다고 추정했고, 이 값은 eax에 저장했습니다.
주소 [ebp-8]는 변수 b에 5라는 값을 저장하는 라인이라고 추정했으므로,
eax=(a) + (b)로 표현할 수 있습니다.
eax=(22) + (5)가 되네요.
0040101A | mov dword ptr ss:[ebp-10], eax | ebp-10=1B(27) c=(a) + (b) |
주소 [ebp-10]에 바로 위에서 표현한 eax의 값을 저장한다는 의미입니다.
ebp-10=1B(27)이 됩니다. 참고로 1B는 27의 16진수 변환자입니다.
동시에 변수들의 식으로 표현하면 c=(a) + (b)로 표현할 수 있습니다.
0040101D | mov ecx, dword ptr ss:[ebp-4] | ecx= (a)= 22 |
ecx 안에 주소[ebp-4]의 저장된 값을 저장해줍니다.
ecx=(a)
ecx=22가 되는군요.
00401020 | sub ecx, dword ptr ss:[ebp-8] | ecx = (a) - (b) (22)-(5) |
ecx에서 주소 [ebp-8]에 저장된 값을 빼줍니다.
ecx에서는 변수a의 22가 저장되어 있었고, [ebp-8]에서는 변수 b의 5가 저장되어 있었으므로
22-5 = 17이 됩니다.
00401023 | mov dword ptr ss:[ebp-C], ecx | ebp-C = (a) - (b) 11(17) |
[ebp-C]라는 주소에서 C는 10진수로 변환하면 12이므로
ebp-C(12)라고 표현하면 편할 것 같습니다.
해당 주소에 (a)-(b)를 저장하는 것과 같으므로
주소 [ebp-C]에 저장된 값은 17이 될 것입니다.
변수 d=a-b로 표현할 수 있습니다.
00401026 | mov edx, dword ptr ss:[ebp-C] | edx d=(a)-(b)=(17) |
edx에 주소[ebp-C]에 저장된 값을 저장해줍니다.
이와 같이 코드를 분석하고 나면 c언어로 기반한 소스코드를 아래까지 유추할 수 있을 것입니다.
int a,b,c,d;
a=16;
b=5;
c= a+b;
d= a-b;
맨 처음 라인 00401003에서 sub esp,10 코드로
esp를 16byte만큼 빼주며 스택 공간을 확보한다고 했습니다.
오퍼랜드에 값을 저장했으니, push로 스택에 데이터를 밀어넣어줍니다.
출력함수를 불러옵니다. 해당 라인까지 [F8]로 실행하고 나면 아래 console창에서 실행 결과를 볼 수 있습니다.
'Hacking&Security > Reversing' 카테고리의 다른 글
[Reversing] 정적 분석,동적 분석, Hex Code,Assembly Code, 패치와 크랙 (0) | 2021.08.31 |
---|---|
[Reversing] 레나 튜토리얼 04 - pixtopianbook파일 registered version으로 변경 (0) | 2021.08.30 |
[Reversing]Ollydbg UDD Directory Absent, UDD 경로 오류 (0) | 2021.08.30 |