외로운 Nova의 작업실
C++와 어셈블리어 본문
이번 문서에는 c++를 어셈블리어로 변환했을때 어떻게되는지 정리해보겠습니다.
- 클래스 정적 할당
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
class Employee
{
public :
int number;
wchar_t 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() {
Employee Nova;
printf("size : %X\n", sizeof(Employee));
Nova.number = 0x1234;
_tcscpy_s(Nova.name, _T("Nova"));
Nova.pay = 0x142;
Nova.ShowData();
return 0;
}
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
class Employee
{
public :
int number;
wchar_t name[128];
long pay;
void ShowData();
void Test();
};
void Employee::ShowData()
{
00007FF631FB1810 mov qword ptr [rsp+8],rcx
00007FF631FB1815 push rbp
00007FF631FB1816 push rdi
00007FF631FB1817 sub rsp,0E8h
00007FF631FB181E lea rbp,[rsp+20h]
00007FF631FB1823 lea rcx,[__F4170C15_test@cpp (07FF631FC10ACh)]
00007FF631FB182A call __CheckForDebuggerJustMyCode (07FF631FB136Bh)
printf("number: %d\n", number);
00007FF631FB182F mov rax,qword ptr [this]
00007FF631FB1836 mov edx,dword ptr [rax]
00007FF631FB1838 lea rcx,[string "number: %d\n" (07FF631FB9CA8h)]
00007FF631FB183F call printf (07FF631FB1190h)
printf("name : %s\n", name);
00007FF631FB1844 mov rax,qword ptr [this]
00007FF631FB184B add rax,4
00007FF631FB184F mov rdx,rax
00007FF631FB1852 lea rcx,[string "name : %s\n" (07FF631FB9CB8h)]
00007FF631FB1859 call printf (07FF631FB1190h)
printf("pay : %d\n", pay);
00007FF631FB185E mov rax,qword ptr [this]
00007FF631FB1865 mov edx,dword ptr [rax+104h]
00007FF631FB186B lea rcx,[string "pay : %d\n" (07FF631FB9CC8h)]
00007FF631FB1872 call printf (07FF631FB1190h)
Test();
00007FF631FB1877 mov rcx,qword ptr [this]
00007FF631FB187E call Employee::Test (07FF631FB10DCh)
return;
}
00007FF631FB1883 lea rsp,[rbp+0C8h]
00007FF631FB188A pop rdi
00007FF631FB188B pop rbp
00007FF631FB188C ret
------------------------------------------------------------
void Employee :: Test()
{
00007FF631FB18B0 mov qword ptr [rsp+8],rcx
00007FF631FB18B5 push rbp
00007FF631FB18B6 push rdi
00007FF631FB18B7 sub rsp,0E8h
00007FF631FB18BE lea rbp,[rsp+20h]
00007FF631FB18C3 lea rcx,[__F4170C15_test@cpp (07FF631FC10ACh)]
00007FF631FB18CA call __CheckForDebuggerJustMyCode (07FF631FB136Bh)
printf("Test function\n");
00007FF631FB18CF lea rcx,[string "Test function\n" (07FF631FB9CD8h)]
00007FF631FB18D6 call printf (07FF631FB1190h)
return;
}
00007FF631FB18DB lea rsp,[rbp+0C8h]
00007FF631FB18E2 pop rdi
00007FF631FB18E3 pop rbp
00007FF631FB18E4 ret
-------------------------------------------------------------------------
int main() {
00007FF631FB19D0 push rbp
00007FF631FB19D2 push rdi
00007FF631FB19D3 sub rsp,218h
00007FF631FB19DA lea rbp,[rsp+20h]
00007FF631FB19DF lea rdi,[rsp+20h]
00007FF631FB19E4 mov ecx,4Eh
00007FF631FB19E9 mov eax,0CCCCCCCCh
00007FF631FB19EE rep stos dword ptr [rdi]
00007FF631FB19F0 mov rax,qword ptr [__security_cookie (07FF631FBC008h)]
00007FF631FB19F7 xor rax,rbp
00007FF631FB19FA mov qword ptr [rbp+1E8h],rax
00007FF631FB1A01 lea rcx,[__F4170C15_test@cpp (07FF631FC10ACh)]
00007FF631FB1A08 call __CheckForDebuggerJustMyCode (07FF631FB136Bh)
Employee Nova;
printf("size : %X\n", sizeof(Employee));
00007FF631FB1A0D mov edx,108h
00007FF631FB1A12 lea rcx,[string "size : %X\n" (07FF631FB9CF0h)]
00007FF631FB1A19 call printf (07FF631FB1190h)
Nova.number = 0x1234;
00007FF631FB1A1E mov dword ptr [Nova],1234h
_tcscpy_s(Nova.name, _T("Nova"));
00007FF631FB1A25 lea rdx,[string L"Nova" (07FF631FB9D00h)]
00007FF631FB1A2C lea rcx,[rbp+14h]
00007FF631FB1A30 call wcscpy_s<128> (07FF631FB12BCh)
Nova.pay = 0x142;
00007FF631FB1A35 mov dword ptr [rbp+114h],142h
Nova.ShowData();
00007FF631FB1A3F lea rcx,[Nova]
00007FF631FB1A43 call Employee::ShowData (07FF631FB1299h)
return 0;
00007FF631FB1A48 xor eax,eax
}
00007FF631FB1A4A mov edi,eax
00007FF631FB1A4C lea rcx,[rbp-20h]
00007FF631FB1A50 lea rdx,[__xt_z+1E0h (07FF631FB9C80h)]
00007FF631FB1A57 call _RTC_CheckStackVars (07FF631FB1307h)
00007FF631FB1A5C mov eax,edi
00007FF631FB1A5E mov rcx,qword ptr [rbp+1E8h]
00007FF631FB1A65 xor rcx,rbp
00007FF631FB1A68 call __security_check_cookie (07FF631FB11A9h)
00007FF631FB1A6D lea rsp,[rbp+1F8h]
00007FF631FB1A74 pop rdi
00007FF631FB1A75 pop rbp
00007FF631FB1A76 ret
특징 : 클래스의 함수먼저 처음에 어셈블링 됩니다. 또한 클래스는 main함수 내에서 선언하면 어셈블러 입장에서 스택에 클래스를 위한 공간을 만들고 클래스의 첫번쨰 주소를 사용하여 각 변수에 접근합니다.
- 클래스 동적 할당
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
class Employee
{
public :
int number;
wchar_t 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() {
Employee *Nova;
Nova = new Employee;
Nova->number = 0x1234;
_tcscpy_s(Nova->name, _T("Nova"));
Nova->pay = 0x142;
Nova->ShowData();
return 0;
}
int main() {
00007FF63AF41B00 push rbp
00007FF63AF41B02 push rdi
00007FF63AF41B03 sub rsp,128h
00007FF63AF41B0A lea rbp,[rsp+20h]
00007FF63AF41B0F lea rcx,[__F4170C15_test@cpp (07FF63AF530ACh)]
00007FF63AF41B16 call __CheckForDebuggerJustMyCode (07FF63AF413F2h)
Employee *Nova;
Nova = new Employee;
00007FF63AF41B1B mov ecx,108h
00007FF63AF41B20 call operator new (07FF63AF4103Ch)
00007FF63AF41B25 mov qword ptr [rbp+0E8h],rax
00007FF63AF41B2C mov rax,qword ptr [rbp+0E8h]
00007FF63AF41B33 mov qword ptr [Nova],rax
Nova->number = 0x1234;
00007FF63AF41B37 mov rax,qword ptr [Nova]
00007FF63AF41B3B mov dword ptr [rax],1234h
_tcscpy_s(Nova->name, _T("Nova"));
00007FF63AF41B41 mov rax,qword ptr [Nova]
00007FF63AF41B45 add rax,4
00007FF63AF41B49 lea rdx,[string L"Nova" (07FF63AF4AC70h)]
00007FF63AF41B50 mov rcx,rax
00007FF63AF41B53 call wcscpy_s<128> (07FF63AF41320h)
Nova->pay = 0x142;
00007FF63AF41B58 mov rax,qword ptr [Nova]
00007FF63AF41B5C mov dword ptr [rax+104h],142h
Nova->ShowData();
00007FF63AF41B66 mov rcx,qword ptr [Nova]
00007FF63AF41B6A call Employee::ShowData (07FF63AF412F3h)
return 0;
00007FF63AF41B6F xor eax,eax
}
00007FF63AF41B71 lea rsp,[rbp+108h]
00007FF63AF41B78 pop rdi
00007FF63AF41B79 pop rbp
00007FF63AF41B7A ret
동적할당으로 객체를 사용하게되면 아래 문장을 통해 클래스가 할당된 힙영역의 주소를 스택에 저장해놓고 변수에 접근하게됩니다.
Employee *Nova;
Nova = new Employee;
00007FF63AF41B1B mov ecx,108h
00007FF63AF41B20 call operator new (07FF63AF4103Ch)
00007FF63AF41B25 mov qword ptr [rbp+0E8h],rax
ecx에 동적할당할 크기를 할당하고 동적할당합니다. 이후 주소는 rax에 담기게되며 이 값은 rbp+0E8h에 담기게됩니다.
- 클래스 생성자와 소멸자
어세블리어는 main함수쪽만 보도록 하겠습니다. 바뀐게 main함수만 이기때문입니다.
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
class Employee
{
public :
int number;
wchar_t name[128];
long pay;
void ShowData();
void Test();
Employee();
~Employee();
};
Employee::Employee()
{
printf("constractor\n");
}
Employee::~Employee()
{
printf("destractor\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() {
Employee *Nova;
Nova = new Employee;
Nova->number = 0x1234;
_tcscpy_s(Nova->name, _T("Nova"));
Nova->pay = 0x142;
Nova->ShowData();
Nova->~Employee();
return 0;
}
int main() {
00007FF72CEF1CA0 push rbp
00007FF72CEF1CA2 push rdi
00007FF72CEF1CA3 sub rsp,148h
00007FF72CEF1CAA lea rbp,[rsp+20h]
00007FF72CEF1CAF lea rcx,[__F4170C15_test@cpp (07FF72CF040ACh)]
00007FF72CEF1CB6 call __CheckForDebuggerJustMyCode (07FF72CEF13FCh)
Employee *Nova;
Nova = new Employee;
00007FF72CEF1CBB mov ecx,108h
00007FF72CEF1CC0 call operator new (07FF72CEF103Ch)
00007FF72CEF1CC5 mov qword ptr [rbp+108h],rax
00007FF72CEF1CCC cmp qword ptr [rbp+108h],0
00007FF72CEF1CD4 je main+4Bh (07FF72CEF1CEBh)
00007FF72CEF1CD6 mov rcx,qword ptr [rbp+108h]
00007FF72CEF1CDD call Employee::Employee (07FF72CEF140Bh)
00007FF72CEF1CE2 mov qword ptr [rbp+118h],rax
00007FF72CEF1CE9 jmp main+56h (07FF72CEF1CF6h)
00007FF72CEF1CEB mov qword ptr [rbp+118h],0
00007FF72CEF1CF6 mov rax,qword ptr [rbp+118h]
00007FF72CEF1CFD mov qword ptr [rbp+0E8h],rax
00007FF72CEF1D04 mov rax,qword ptr [rbp+0E8h]
00007FF72CEF1D0B mov qword ptr [Nova],rax
Nova->number = 0x1234;
00007FF72CEF1D0F mov rax,qword ptr [Nova]
00007FF72CEF1D13 mov dword ptr [rax],1234h
_tcscpy_s(Nova->name, _T("Nova"));
00007FF72CEF1D19 mov rax,qword ptr [Nova]
00007FF72CEF1D1D add rax,4
00007FF72CEF1D21 lea rdx,[string L"Nova" (07FF72CEFAC90h)]
00007FF72CEF1D28 mov rcx,rax
00007FF72CEF1D2B call wcscpy_s<128> (07FF72CEF1325h)
Nova->pay = 0x142;
00007FF72CEF1D30 mov rax,qword ptr [Nova]
00007FF72CEF1D34 mov dword ptr [rax+104h],142h
Nova->ShowData();
00007FF72CEF1D3E mov rcx,qword ptr [Nova]
00007FF72CEF1D42 call Employee::ShowData (07FF72CEF12F8h)
Nova->~Employee();
00007FF72CEF1D47 xor edx,edx
00007FF72CEF1D49 mov rcx,qword ptr [Nova]
00007FF72CEF1D4D call Employee::`scalar deleting destructor' (07FF72CEF147Eh)
return 0;
00007FF72CEF1D52 xor eax,eax
}
00007FF72CEF1D54 lea rsp,[rbp+128h]
00007FF72CEF1D5B pop rdi
00007FF72CEF1D5C pop rbp
00007FF72CEF1D5D ret
생성자 코드는 아래와 같습니다.
00007FF6F5CD1BFD call Employee::Employee (07FF6F5CD140Bh)
00007FF6F5CD1C02 mov qword ptr [rbp+118h],rax
00007FF6F5CD1C09 jmp main+56h (07FF6F5CD1C16h)
00007FF6F5CD1C0B mov qword ptr [rbp+118h],0
00007FF6F5CD1C16 mov rax,qword ptr [rbp+118h]
00007FF6F5CD1C1D mov qword ptr [rbp+0E8h],rax
00007FF6F5CD1C24 mov rax,qword ptr [rbp+0E8h]
00007FF6F5CD1C2B mov qword ptr [Nova],rax
소멸자 코드는 아래와 같습니다.
Nova->~Employee();
00007FF72CEF1D47 xor edx,edx
00007FF72CEF1D49 mov rcx,qword ptr [Nova]
00007FF72CEF1D4D call Employee::`scalar deleting destructor' (07FF72CEF147Eh)
'Computer App Penetesting > Reversing' 카테고리의 다른 글
RP 2006년 버전 크랙 (0) | 2023.02.05 |
---|---|
creackme 시리즈 - 2(crackme10.exe) (4) | 2023.01.26 |
리버싱 엔지니어링 바이블 - 1(함수 호출 규약) (0) | 2023.01.18 |
creackme 시리즈 - 1(crackme6.exe) (0) | 2022.12.29 |
리버싱 입문 - 11(공부 종료) (0) | 2022.12.27 |
Comments