C++ 분석
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 33 34 35 36 37 38 39 40 41 42 | #include <iostream> #include <Windows.h> #include <tchar.h> class Employee { public: int number; char name[128]; long pay; void ShowData(); void Test(); }; void Employee::ShowData() { printf("Number: %d\n", number); printf("Name: %s\n", name); printf("pay: %d\n", pay); Test(); return; } void Employee::Test() { printf("Test Function\n"); return; } int main(int argc, char* argv[]) { Employee k3y6reak; printf("Size: %x\n", sizeof(Employee)); k3y6reak.number = 0x4855; strcpy(k3y6reak.name, "키브레이크"); k3y6reak.ShowData(); return 0; } | cs |
일단 위와 같은 소스코드를 작성합니다. 이때 릴리즈 모드, 최적화 옵션은 제거합니다.
이 부분이 main 함수의 시작입니다.
E416C3 주소를 보면 PUSH 88을 하고 있습니다. printf()에서 인자로 "size: %x\n"과 sizeof(Employee)가 있으므로 2번째 인자인 sizeof(Employee)가 0x88이 됩니다.
E416D6 주소에서 MOV DWORD PTR SS:[EBP-8C], 4855 로 되어있습니다. 소스코드에서는 k3y6reak.number에 0x4855가 들어갑니다. 즉 k3y6reak.number의 주소가 EBP-8C라는 것이죠.
그 다음 구간은 strcpy 구간이고 CALL ShowData 부분이 나타납니다.
ShowData 부분입니다.
C++에서 객체는 ECX의 값에 주소를 넣는다고 했습니다.
E41634에서 MOV DWORD PTR SS:[EBP-=4], ECX 명령어가 나타나는데, 해당 부분의 ECX 값이 19F80C 입니다. 해당 값을 EBP-4인 19F800에 넣습니다.
그리고 그 값을 EAX에 넣고 이제 그 값을 ECX에 넣고 printf로 출력합니다.
이 부분에는 main에서 저장한 0x4855 값을 가져와 출력합니다.
두번째 printf 부분은 E41648 부분부터 시작합니다.
E4164B 에서 EBP-4의 값을 EDX에 저장합니다. 해당 값은 19F80C로 객체 주소를 나타냅니다. 그리고 ADD EDX, 4를 통해서 주소를 +4 합니다.
그리고 printf를 합니다. +4를 한다는 것을 통해서 다음 변수에 참조한다는 것을 알 수 있습니다. ECX에 객체의 주소를 담고있으니 EDX의 값에 다음 멤버변수가 들어간다고 생각할 수 있습니다.
마찬가지로 다음 printf도 같은 원리로 작동합니다.
그리고 다음으로는 Test Function이 나타납니다.
이 부분은 별다른 기능이 없으니 넘어가도록 하겠습니다.
객체를 동적할당 해체하는 경우
이번에는 객체를 new로 동적할당하고 delete로 해체하는 부분에 대해서 알아보도록 하겠습니다.
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 | #include <iostream> #include <Windows.h> #include <tchar.h> class Employee { public: int number; char name[128]; long pay; void ShowData(); void Test(); }; void Employee::ShowData() { printf("Number: %d\n", number); printf("Name: %s\n", name); printf("pay: %d\n", pay); Test(); return; } void Employee::Test() { printf("Test Function\n"); return; } int main(int argc, char* argv[]) { Employee *pk3y6reak; pk3y6reak = new Employee; pk3y6reak->number = 0x4855; strcpy(pk3y6reak->name, "키브레이크"); pk3y6reak->pay = 0x100; pk3y6reak->ShowData(); delete pk3y6reak; return 0; } | cs |
위 어셈코드가 main 함수 부분입니다.
10E16BB에서 CALL하는 부분이 나타나는데 이 부분이 new로 동적할당을 하는 부분입니다. 그런데 그전에 PUSH 88을 통해서 스택에 값을 쌓아두는데 이 값은 앞서 살펴본 것처럼 클래스의 크기입니다.
CALL을 통해서 반환된 값인 EAX의 값이 곧 Employee *pk3y6reak에 해당하는 pk3y6reak 포인터입니다.
객체를 동적할당으로 사용하는 경우에는 스택에 값을 쌓아서 사용을 하는 것이 아니라 new로 메모리를 할당해서 받은 heap 공간에 넣어서 사용됩니다.
스택을 사용하게 되는 경우에는 mov [ebp+4], 100과 같은 형식으로 스택에 값을 넣게되지만 동적할당으로 사용되면 heap 영역을 사용하기 때문에 mov dword [edx+84], 100과 같이 사용됩니다.
생성자와 소멸자
이번에는 생성자와 소멸자 부분에 대해서 분석해 보겠습니다.
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 49 50 51 52 53 54 55 56 57 | #include <iostream> #include <Windows.h> #include <tchar.h> class Employee { public: int number; char name[128]; long pay; Employee(); ~Employee(); void ShowData(); void Test(); }; Employee::Employee() { printf("constructor\n"); } Employee::~Employee() { printf("Desstructor\n"); } void Employee::ShowData() { printf("Number: %d\n", number); printf("Name: %s\n", name); printf("pay: %d\n", pay); Test(); return; } void Employee::Test() { printf("Test Function\n"); return; } int main(int argc, char* argv[]) { Employee *pk3y6reak; pk3y6reak = new Employee; pk3y6reak->number = 0x4855; strcpy(pk3y6reak->name, "키브레이크"); pk3y6reak->pay = 0x100; pk3y6reak->ShowData(); delete pk3y6reak; return 0; } | cs |
위 어셈코드가 main 함수 입니다.
위 어셈코드는 생성자 부분입니다.
해당 부분을 넘어가게되면 어셈코드가 해석되지 않은 채 진행됩니다.
위 코드는 소멸자 부분입니다.
'High Level Technique > Reversing' 카테고리의 다른 글
Obfuscation (난독화) (0) | 2016.09.07 |
---|---|
Native API (0) | 2016.08.24 |
Debug Blocker (0) | 2016.08.10 |
PE Image Switching (2) | 2016.08.10 |
Self Creation Debugging (0) | 2016.08.09 |