리버스 엔지니어링을 독학으로 얼마나 가능할진 모르겠으나, 최대한 책과 유튜브 등을 보면서 공부를 해보겠다.

 

시작에 앞서 리버스 엔지니어링에 대해 잠깐 설명하자면 C, C++ 등 고급언어(high level language) 즉 사람이 알아보기 쉽게 만들어진 언어로 개발한 프로그램, 하드웨어등을 IDA, Windbg, Ghidra 등의 도구를 사용하여 분석 후 보다 더 안전하게 만드는 목적이며, 이를 악용하면 인터넷상 존재하는 벽돌판 게임, 인게임 핵등이 만들어진다.   

 

이제 본론으로 들어가면 제목, 제목 하단 내용과 동일하게 정말 어디까지 목표가 될지 모르겠지만 해볼 수 있는 한 계속해서 진행할 스터디다. 

 

exe의 파일의 예상 소스코드 

#include <stdio.h>

void main(){
	printf("Hello, World\n");
    
    return 0;
}

 

 

해당 코드를 리버싱 프로그램으로 돌려보면 

 

 

해당 창과 같이 나오게 된다. 

  • 1번 창은 실행파일의 함수를 모아놓는다.
  • 2번 창은 함수에 있는 코드를 가지고 와서 보여주는 메인 화면이며 위에 String, Hex view, Structures, Enums, imports, Export 등 프로그램을 쉽고 빠르게 분석할 수 있게 존재하는 것이다.
  • 3번 창은 이름 그대로 출력을 하는 동시에 IDC에 입력을 하는 공간이기도 하다. 

 

해당 창에서 

text:00000001400010F6  lea     rax, aHelloWorld ; "Hello, world!\n"

이 코드 부분에 함수를 들어가 보면

rdata:000000014001A140 aHelloWorld     db 'Hello, world!',0Ah,0

로 들어가진다.

문자열(String)로 보면 더 자세히 알 수 있다.

 

 

함수 sub_140001000로 들어가서 

.text:00000001400010F6  lea  rax, aHelloWorld ; "Hello, world!\n"

해당 코드를 조금 더 알아보기 쉽게 단축키 F5를 누르면 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  Sleep(0x3E8u);
  qword_14001DBE0 = (__int64)"Hello, world!\n";
  sub_140001060((__int64)"Hello, world!\n");
  return 0;
}

위와 같이 나온다. 

 

 

위 매개변수에서에선 argc, argv, envp로 3개의 인자를 받는다.

  • Sleep함수를 호출하여 1초 대기한다.
  • qword_14001DBE0에 “Hello, world!\n” 문자열의 주소를 넣은 후
  • sub_140001060에 “Hello, world!\n” 를 인자로 전달하여 호출한다. 
  • 그리고 0을 반환하는 코드의 형태이다.

 

 

아래 코드에서  sub_140001060로 클릭을 해보면 

 

 

아래의 코드로 나온다.

__int64 sub_140001060(__int64 a1, ...)
{
  FILE *v1; // rax
  va_list va; // [rsp+58h] [rbp+10h] BYREF

  va_start(va, a1);
  v1 = _acrt_iob_func(1u);
  return (unsigned int)sub_140001010(v1, a1, 0i64, (__int64 *)va);
}

 

 

va_start는 인자값을 가지고 있기에 void main을 뜻하는거 였고 v1의 부분은 printf 로 생각할 수 있다.

+ Recent posts