1.5 리버싱 기초 - C 문법과 어셈블리어

악성코드 분석

2018. 8. 25. 21:21

반응형

- 03 if 문

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
28
29
30
31
32
33
34
35
36
37
38
39
40
// C
int Temp(int a)
{
    int b = 1;
 
    if(a==1) {
        a++;
    } else {
        b++;
    }
 
    return b;
}
 
int main(int argc, char* argv[])
{
    Temp(1);
}
 
// 어셈블리어
.text:00401000    push    ebp
.text:00401001    mov ebp, esp
.text:00401003    push    ecx
.text:00401004    mov dowrd ptr [ebp-4], 1
.text:00401008    cmp dowrd ptr [ebp+8], 1
.text:0040100F    jnz short loc_4010C
.text:00401011    mov eax, [ebp+8]
.text:00401014    add eax, 1
.text:00401017    mov [ebp+8], eax
.text:0040101A    jmp short loc_401025
.text:0040101C loc_40101C:
.text:0040101C    mov eax, [ebp-4]
.text:0040101F    add ecx, 1
.text:00401022    mov [ebp-4], ecx
.text:00401025
.text:00401025 loc_401025:
.text:00401025    mov eax, [ebp-4]
.text:00401028    mov esp, ebp
.text:0040102A    pop ebp
.text:0040102B    retn
cs


이 코드는 간단히 말하면 a가 1일 경우 b는 1이 되고,

a가 1이 아니면 b는 2가 됩니다.


어셈블리 코드에서 보이는 loc_`````는

없는것과 마찬가지 입니다. 약간 주석같은 개념으로,

jmp할때 어디로 가는지 찾기 쉬우라고 작성해놓은 코드입니다.


.text:0040100F    jnz short loc_4010C

이 코드는 위에서 비교한게 맞다면 해당 주소로 가라. 라는 뜻을 가진 코드입니다.


즉, 바로 위 코드는 c코드와 비교하면 else 부분이기 때문에

a가 1이 아닐시 이동을 해줍니다.


if문은 cmp와 jmp만 잘봐주면 문제가 없습니다 :)


- 04 반복문

- 반복문은 for, while, goto 등이 있으나, 컴퓨터 입장에서는 결국 카운터 레지스터를 이용한 반복이다.
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
28
29
30
31
32
33
34
35
36
37
// C
int Temp(int a)
{
    int d;
    
    for (int i = 0; i<=0x100; i++)
        {
            c--;
            d++;
        }
 
    return c+d;
 
// 어셈블리어
.text:00401000    push    ebp
.text:00401001    mov ebp, esp
.text:00401003    sub esp, 8
.text:00401006    mov dowrd ptr [ebp-8], 0
.text:0040100D    jmp short loc_401018
.text:0040100F    mov eax, [ebp-8]
.text:00401012    add eax, 1
.text:00401015    mov [ebp-8], eax
.text:00401018    cmp dword ptr [ebp-8], 100h
.text:0040101F    jg    short loc_401035
.text:00401021    mov ecx, [ebp+8]
.text:00401024    sub ecx, 1
.text:00401027    mov [ebp+8], ecx
.text:0040102A    mov edx, [ebp-4]
.text:0040102D    add edx, 1
.text:00401030    mov [ebp-4], edx
.text:00401033    jmp short loc_40100F
.text:00401035    mov eax, [ebp+8]
.text:00401038    add eax, [ebp-4]
.text:0040103B    mov esp, ebp
.text:0040103D    pop ebp
.text:0040103E    retn
cs


.text:0040100D    jmp short loc_401018 코드는 무조건 점프이기 때문에

.text:00401018    cmp dword ptr [ebp-8], 100h 바로 이 코드로 점프합니다.

.text:0040101F    jg    short loc_401035 코드에서 jg는 Jump if greater than(less than이란것도 있다.)

의 약자입니다. 뜻은 ~~보다 크다면. 입니다.


즉, 비교한 값이 크다면 401035로 점프를 합니다.

for문을 끝내는 역할도 해줍니다.


코드는 계속 돌아가다가 100인것이 확인된다면 for문에서 나가게 됩니다.


- 05 구조체와 API Call

C++ 코드
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
28
29
30
31
32
void RunProcess()
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
 
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
 
    // Start the child process.
    if(!CreateProcess(Null,
        "MyChildProcess",
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        &si,
        &pi))
    {
        printf("CreateProcess failde.\n");
        return;
    }
 
    // Wait until child process exits.
    WaitForSingleObject(pi .hProcess, INFINTE);
 
    // Close process and thread handles.
    CloseHandle(pi .hProcess);
    CloseHandle(pi .hProcess);
}
cs


어셈블리 코드
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
0x401000    PUSH    EBP
0x401001    MOV EBP, ESP
0x401003    SUB ESP, 54
0x401006    PUSH    44
0x401008    PUSH 0
0x40100A    LEA EAX, DWORD PTR SS:[EBP-54]
0x40100D    PUSH    EAX
0x40100E    CALL    calling.004011A0
0x401013    ADD ESP, 0C
0x401016    MOV DWORD PTR SS:[EPB-54], 44
0x40101D    PUSH    10
0x40101F    PUSH     0
0x401021    LEA ECX, DWORD PTR SS:[EBP-10]
0x401024    PUSH    ECX
0x401025    CALL    calling.004011A0
0x40102A    ADD ESP, 0C
0x40102D    LEA EDX, DWORD PTR SS:[EBP-10]
0x401030    PUSH    EDX
0x401031    LEA EAX, DWORD PTR SS:[EBP-54]
0x401034    PUSH    EAX
0x401035    PUSH    0
0x401037    PUSH    0
0x401039    PUSH    0
0x40103B    PUSH     0
0x40103D    PUSH    0
0x40103F    PUSH    0
0x401041    PUSH    calling.00407030
0x401046    PUSH    0
0x401048    CALL    DWORD PTR DS:CreateProcesssA
0x40104E    TEST    EAX, EAX
0x401050    JNZ SHORT calling.00401061
0x401052    PUSH    calling.00407040
0x401057    CALL    calling.0040116F
0x40105C    ADD ESP, 4
0x40105F    JMP SHORT calling.00401081
0x401061    PUSH    -1
0x401063    MOV ECX, DWORD PTR SS:[EBP-10]
0x401066    PUSH    ECX
0x401067    CALL    DWORD PTR DS:WaitForSingleObject
0x40106D    MOV EDX, DWORD PTR SS:[EBP-10]
0x401070    PUSH    EDX
0x401071    CALL    DWORD PTR DSS:CloseHandle
0x401077    MOV EAX, DWORD PTR SS:[EBP-C]
0x40107A    PUSH    EAX
0x40107B    CALL    DWORD PTR DS:CloseHandle
0x401081    MOV ESP, EBP
0x401083    POP EBP
0x401084    RETN
cs


1~2번째 코드는 함수 프롤로그 이고,

3번째 코드는 54h 바이트 스택 확보를 합니다. 두개의 구조체를 확보한겁니다. (0x44하나 0x10하나 총 0x54)

4~9번째 코드는 ZeroMemory() _STARTUPINFO 구조체를 초기화 해주고

10번째 코드는 _STARTUPINFO 구조체의 첫 번째 멤버 변수에 0x44를 삽입 해줍니다.

11~16번째 코드는 ZeroMemory() _PROCESS_INFORMATION 구조체를 초기화 합니다.


16~29번째 코드는 CreateProcess()를 호출하며 인자를 역순으로 전달합니다.

30~31번째 코드는 리턴 값이 NULL인지 검사하며 NULL이 아닐 경우 점프시킵니다.

32~35번째 코드는 리턴 값이 NULL인 경우 "Create Process faild.Wa"를 출력시킵니다.


36~45번째 코드는 WaitingForSingleObject & CloseHandle을 진행하며

46~48번째 코드는 함수 에필로그 입니다.

반응형

'악성코드 분석' 카테고리의 다른 글

[리버싱] crackme0x00a WRITE UP  (0) 2018.10.27
리버싱 기초 - Lena 듀토리얼 01번 풀이  (0) 2018.09.01
1. 리버싱 기초(2)  (3) 2018.08.25
1. 리버싱 기초  (2) 2018.08.19