키워드 : #클래스 #멤버 변수 #멤버 함수 #캡슐화 #상속
클래스/구조체 구분하는 법
클래스를 사용할 경우 this포인터를 사용
어셈블리에서는 클래스의 멤버함수 호출 전에 인스턴스의 주소를 ecx에 저장한다. (함수의 호출규약 참고)
함수 내부에서는 받아온 ecx 값을 스택에 저장한 뒤 사용한다.
함수가 시작하자마자 ecx값을 스택에 저장한다면 클래스를 사용한다는 사실을 유추할 수 있다!
+) 스택에 저장한 this 포인터값을 사용하는 방법 (멤버변수에 접근할때)
1. 그 값을 아무 레지스터에 복사한다.
2. 해당 레지스터에다가 필요한 offset을 더한다. (멤버변수가 여러개일때)
3. push해서 함수의 인자로 사용하는 등.. 사용한다!
인스턴스 변수가 전역변수라면?
해당 인스턴스는 .data 섹션에 존재한다.
어셈블리에서는 dword_409908이나 dword_40998C와 같이 멤버변수의 주소를 이용해 직접 접근이 가능한다.
하지만 이 때에도 멤버함수를 호출할 때는 this 포인터를 ecx에 저장한 뒤 이 값을 사용한다.
객체의 동적할당과 해제
new나 malloc과 같은 코드로 객체를 동적할당해주면 함수의 스택에는 해당 객체의 시작주소를 가리키는 포인터값 하나만 저장된다.
이 때에는 객체를 가리키는 포인터 값에 오프셋을 더하는 방식으로 클래스의 멤버 변수에 접근한다.
ex) 동적할당을 받지 않을 때
.text:004010A2 mov [ebp+var_4], 100h
동적할당을 받을 때
.text:004010F4 mov eax, [ebp+var_4] .text:004010F7 mov dword ptr [eax+84h], 100h
생성자와 소멸자
생성자와 소멸자도 어셈블리에서는 다른 함수와 다를 바 없는 형태로 표현된다.
대신 생성자와 소멸자를 정의해주면 이 함수들을 호출하는 함수에 자동적으로 다음과 같은 예외처리 코드가 만들어진다.
.text:004010DF push 0FFFFFFFFh .text:004010E1 push offset unknown_libname_9 ; Microsoft VisualC 2-8/net runtime .text:004010E6 mov eax, large fs:0 .text:004010EC push eax .text:004010ED mov large fs:0, esp
참고로, C++문법에서는 보이지 않지만 생성자 함수도 return 값을 가지는데 바로 객체의 시작주소이다.
생성자와 소멸자 함수를 호출할 때도 this 포인터를 ecx에 저장하고 시작하는 것은 똑같다.
TIP) 할당 코드 직후에 어떤 함수가 등장하고, 그 함수의 리턴값을 이용해서 여러 변수를 제어하는 모습이 보인다면 클래스와 관련된 내용이라 짐작할 수 있다!
보통 생성자에서는 멤버변수를 0으로 세팅하는 작업을 주로 한다. 만약 memset()을 이용하는 등 비슷한 작업을 하는 함수가 보인다면 생성자를 의심해볼 수 있다!
소멸자에서는 각종 변수의 메모리를 해제하거나 close관련 API를 호출하는 경우가 많다!
캡슐화 분석
private과 같은 연산자는 컴파일러 내부에서 개발자에게 주의를 주는 것이고 바이너리로 변경되면 다른 함수나 변수와 마찬가지로 작동한다.
즉, 바이너리 상에서는 특정 함수나 변수가 private 속성을 띠는지 아닌지 파악할 방법이 없다.
다형성 구조 파악
가상함수의 경우 vtable에 함수의 목록이 저장된다.
vtable은 .rdata 섹션에 위치한다. (.rdata 섹션에 보관된 함수 포인터를 발견하면 이것을 가상함수라 유추할 수 있다)
따라서 가상함수를 호출할 때는 vtable의 주소를 가져온 다음 vtable내에서의 해당 함수의 offset을 이용해 해당 함수를 호출한다.
또한 생성자와 소멸자에 다음과 같은 코드가 생성된다. (세번째 줄)
.text:00401098 mov [ebp+var_4], ecx .text:0040109B mov eax, [ebp+var_4] .text:0040109E mov dword ptr [eax], offest off_4070C0 ; vtable
'리버스 엔지니어링 바이블' 카테고리의 다른 글
05 PE 헤더 (PE Header) (0) | 2018.11.10 |
---|---|
04 DLL 분석 (0) | 2018.10.17 |
02 C 문법과 디스어셈블링 (0) | 2018.10.14 |
01 리버스 엔지니어링만을 위한 어셈블리 (0) | 2018.10.14 |
[리버스 엔지니어링 바이블] 책 소개 (0) | 2018.10.14 |