Self-Improvement

x64dbg 사용법 및 리버싱 기초 (CASE 구문, For문) 본문

리버싱 기초

x64dbg 사용법 및 리버싱 기초 (CASE 구문, For문)

JoGeun 2020. 4. 29. 15:56

CASE구문 소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
 
int main() {
    int n;
    printf("INput number:");
    scanf_s(" %d",&n);
    printf("before switch statement\n");
    switch (n) {
    case 0:printf("[zero]");
        break;
    case 1:printf("[one]");
        break;
    case 2:printf("[two]");
        break;
    case 3:printf("[three]");
        break;
    case 4:printf("[four]");
        break;
    case 5:printf("[five]");
        break;
    defaultprintf("[error]");
        break;
 
    }
    printf("after whitch statemenet\n");
    return 0;
}
cs

 

CASE문을 이용한 소스코드이며 어셈블리어로 main을 찾아가서 확인해준다.

 

"call 831046"은 printf()함수로 그전의 "push 837B30"으로 "Input number :" 문자열을 인자로 줬다.

 

"add esp,4"로 esp의 위치를 4만큼 더하며 "lea eax,dword ptr ss:[ebp-C]"로 ebp-C의 주소값을 eax에 할당해준다.

 

ebp-c의 주소는 0097FA44로 eax에 할당된다.

 

"push eax"로 eax값을 스택에 저장해주며 "push 837B50"으로 837B50 메모리 주소의 데이터 값 %d도 스택에 저장해주면 "call 831393"으로 scanf_s()함수를 호출하는데 인자로 사용된다.

스택

 

scanf_s()함수는 입력값의 주소를 저장하게 됨으로 그전의 인자로 받은 주소 0097FA44 주소에 입력값이 저장될 것이다.

입력 값은 4로 하고 0097FA44 주소의 값을 확인해보면 4가 들어가있다.

 

"push 837B54"로 before switch statement 문자열을 인자로 받아 printf()함수가 실행된다.

 

"mov eax,dword ptr ss:[ebp-c]"로 ebp-c의 데이터 값을 eax에 할당한다. 이때 ebp-c는 위에 분석을 하였듯이 0097FA44이며 값은 4을 나타내고 있다.

 

그 다음 "mov dword ptr ss:[ebp-D4], eax"로 eax의 값 4를 ebp-D4에 할당해준다.

"cmp dword ptr ss:[ebp-D4],5" ebp-D4에 저장된 4와 5를 비교하는 구문으로 "ja 835116"은 ebp-D4의 값이 5보다 클 경우에 835116주소로 이동하는 것이다. 835116으로 이동하게 되면 [error] 문구가 뜨며 종료가 되어진다.

 

하지만 ebp-D4의 값은 4임으로 5보다 작아서 바로 아래 라인으로 이어진다. "mov ecx, dword ptr ss:[ebp-D4]"로 ecx에 4가 할당되어지며 "jmp dword ptr ds:[ecx*4+83517c]"로 ecx의 값에 4를 곱하여 메모리 83517c의 주소에 더해지는 메모리 주소의 값으로 이동하게 되는 것이다.

 

ecx는 4였음으로 4x4+83517c의 값은 83518c이며 해당 메모리 주소의 값의 4바이트를 확인하면 0083508F로 이동하라는 뜻이 된다. 

 

0083508F주소는 "push 837c1c"로 [four] 값이 들어있으며 printf()함수를 만나 출력이 이루어진다.

 

끝에는 다시 printf()함수를 더 만나서 after switch statement 구문을 만나고 종료가 된다.

 

여기 위의 글에서 5와 비교하는 구문은 switch case 구문에서 정수 값 중 제일 큰 값이 5인것으로 볼 수 있다. 실제로 소스코드에서도 그렇게 되어있다.

 


 

For구문 소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int func(int x, int y, int z) {
    int result;
    result = x + y + z;
    return result;
}
 
int main(void) {
    int i, n, sum, value;
    printf("strp #1\n");
    sum = 0;
    for (i = 1; i <= 10; i++) {
        sum += 1;
    }
    printf("step #2\n");
    value = func(123);
    return 0;
 
}
cs

 

main으로 들어가준 뒤 확인해준다.

 

"push 817b30"은 메모리에 있는 817b30주소의 데이터값을 스택에 넣으며 "call 811046"을 통해 printf()함수 인자로 넘겨주고 출력을 해준다.

오타..

 

"mov dword ptr ss:[ebp-20],0", "mov dword ptr ss:[ebp-8],1"은 0과 1을 ebp-20, ebp-8 위치 값에 넣어주는 것이며 이 부분은 지역변수를 말하기도 한다.

v1=0

v2=1

"jmp 81508E"는 81508E 주소로 이동하는 것을 뜻한다.

 

81508E 주소로 이동하면 "cmp dword ptr ss:[ebp-8],A"로 ebp-8 값인 1과 A(10진수로 10)을 비교하여 "jg 81509F" 으로 ebp-8이 A보다 클시에 81509F로 이동하게 되며 ebp-8이 작기 때문에  "mov eax, dword ptr ss:[ebp-20]"으로 이어진다.

 

"mov eax,dword ptr ss:[ebp-20]"은 ebp-20의 값인 0을 eax에 저장하게 된다.

"add eax,1" eax의 값에 1을 더해준다.

"mov dword ptr ss:[ebp-20], eax" eax의 값을 ebp-20에 다시 저장하게 된다.

위 3가지 행동은 v1+=1로 봐도 된다.

"jmp 815085"로 다시 위로 올라가게 되고 ebp-8을 eax로 저장한 후 eax값을 1 더하고 다시 eax를 ebp-8로 이어지게 된다. 

그리고 다시 A랑 비교하여 작을시에 아래의 루틴을 반복하게 된다. 즉 ebp-8이 A보다 클때까지 되며 ebp-20도 1씩 더해주게 된다.

 

반복 루틴이 끝나면 "push 817C2C"로 817C2C 데이터를 스택에 넣고 "call 811046"인 printf()함수를 호출하여 출력하게 된다.

 

push로 3,2,1을 스택에 넣고 "call 81139D"로 func(int, int,int) 함수를 호출하며 인자로 사용하게 되며 F7로 해당 함수가 어떤 작업을 하는지 확인해본다.

 

func(int,int,int)함수 루틴에서도 중요한 부분만 보면 된다.

 

"mov eax, dword ptr ss:[ebp+8]"로 인자로 받았던 숫자중 1을 eax에 할당하게 된다.

"add eax, dword ptr ss:[ebp+c]"은 ebp+c의 데이터는 2로 eax에 더하게 된다.

"add eax, dword ptr ss:[ebp+10]"은 ebp+10의 데이터 3이 eax에 추가적으로 더하게 되어 eax는 3+2+1로 6이된다.

"mov dword ptr ss:[ebp-8],eax"로 eax의 값인 6을 ebp-8로 할당해준다. 지역변수

"mov eax, dword ptr ss:[ebp-8]"로 ebp-8의 값을 eax로 할당해주고 해당 func(int,int,int)가 종료가 된다.

 

전에 말했듯이 eax는 리턴값을 가지기도 하며 func(int,int,int)함수에서 6을 리턴받은 것이다.

원래 함수로 돌아온뒤 "mov dword ptr ss:[ebp-2c],eax"로 ebp-2c에 eax값을 할당해주고 종료 된다.

 

 

* 잘못된거나 이상한점이 존재한다면 알려주시기 바랍니다. 환영입니다.