IDA 도구에 대한 사용 방법과, 디컴파일된 코드를 여러 기능을 통해 원본 코드와 비슷한 코드로 복구하는 실습을 진행했다.
#include <stdio.h>
#include <Windows.h>
#pragma warning(disable:4996)
struct Human
{
char name[50];
int age;
char gender;
char email[50];
};
int main(int argc, char** argv)
{
Human human;
strcpy(human.name, "tonix");
human.age = 24;
human.gender = 'M';
sprintf(human.email, "%s@gmail.com", "tonix0114");
printf("%s %d %c %s", human.name, human.age, human.gender, human.email);
}
해당 코드는 tonix님이 제공해주셨다. 위 코드가 exe 파일로 컴파일하여 IDA로 분석하면서 여러 기능을 사용해볼 것이다.
exe파일을 IDA에 던지면, 다음과 같은 main 함수를 확인할 수 있다. Structures 기능으로 IDA에서 Human 구조체를 생성하여 적용시킬 것이다.
sub_411465 함수에서 email 형태로 된 문자와 %s로 받는 부분에 tonix0114가 들어감을 예상할 수 있다. 해당 함수는 sprintf로 추정되며, 해당 들어가는 부분이 email임을 확인하고 구조체로 넉넉하게 100byte를 부여했다.
코드 위에서 human이라는 구조체를 부여했을 때, 0x38 부분에서 끊긴다. 따라서 첫번째 구조체 부분은 0x38만큼의 크기를 가지고 있음을 예상할 수 있다. 이 부분은 패딩된 값일 수도 있다.
코드에서 생성자 부분이다. 해당 부분에서 vftable을 확인 할 수 있는데, 이 주소에 보면 두개의 함수 주소를 확인할 수 있다.
첫번째 함수를 찾아가서, this 인자의 자료형을 y 키로 1byte로 변경해준다. 그러면 이 함수는 *(this + 56)을 리턴 하는 것을 확인할 수 있다. 따라서 main에서 확인한 24라는 값을 리턴해주는 함수임을 추측했다.
그 다음에 나오는 값을 this[60]이다. 앞서 *(this+56)에서 4byte 더 추가됐으므로, 앞서 찾은 24라는 값은 int 형임을 알 수 있었다. 앞서 main에서는 ‘M’이라는 값이 해당 구조체 영역에 들어가 있다.
문제 원본 코드를 받았기 때문에, Human 구조체임을 확인할 수 있었다. 실제 그 정보가 없었다면 유추할 수는 있지만 쉽지 않았을 것 같다.
정보가 있는 상황이기 때문에 age와 gender 값을 리턴해주는 함수임을 알 수 있었고, 해당 함수의 이름을 바꿔주었다.
잘 맞춰줬다고 생각했지만, main에서 자꾸 4바이트가 이상했다..
해당 코드에서 C++에서 객체(?)를 넘길 때 this가 먼저 세팅된다는 것을 깨달았다.
Structures에 제일 처음 부분에 this 멤버를 추가해주었더니, 코드가 한결 깔끔해진 모습이다.
하지만, 원본 코드와 비교했을 때, printf의 인자가 제대로 인식하지 못한 것 같다.
y를 통해 해당 인자를 맞춰주었더니, cpp 코드와 동일한 함수 형태가 완성되었다.
이때, human + 61은 구조체에서 확인하면 email을 나타낸다.
물론 해당 실습은 원본 코드를 알고있기 때문에, Human 구조체의 구성이라는 것을 쉽게 파악할 수 있었다.
실제 실행파일을 IDA에서 분석한다면, 용량도 엄청나고 분석 난이도도 높을 것이다.
기능을 적절히 잘 사용한다면, IDA 디컴파일 코드를 분석하는데 큰 도움이 될 것 같다.