ImagePrc.exe 를 x32dbg - xAnalyzer로 분석하면 위와 같이 FindResourceA 함수에서 두 번째 인수인 리소스 이름으로 65를 사용한 것을 확인할 수 있다. FindResourceA 함수의 두 번째 인수는 포인터가 아닐 경우 MAKEINTRESOURCE(ID) 이다.
■ Stack[-0x1c]... local_1c XREF[1]:00401068 => 1바이트의 local_1c 변수가 00401068에서 사용된다.
local_1c 부분에 마우스를 올리면 undefined Byte, Length: 1 이라고 표시되는데, 위 변수와의 차를 계산해 보면(0x1c-0xc) 실제로는 1바이트가 아닌 16(0x10) 바이트인 것을 알 수 있고 기본 자료형이 아닌 것을 알 수 있다.
■ Stack[-0x60]... local_60 XREF[2]:0040105e => 1바이트의 local_60 변수가 0040105e에서 사용된다. (그리고 1개 더 있다)
마찬가지로 위 변수와의 차를 계산해 보면(0x60-0x1c) 68(0x44) 바이트의 자료형이다.
■ Stack[-0x164]... local_164 XREF[3]:00401068 => 1바이트의 local_164 변수가 00401031에서 사용된다. (그리고 2개 더 있다)
마찬가지로 위 변수와의 차를 계산해 보면(0x164-0x60) 260(0x104)바이트의 자료형이다.
모두 -0xXX의 주소값을 갖는데, EBP-0xXX를 의미하며 함수의 지역변수를 의미하는거 같다.
Base of Code를 디컴파일한 내용을 다시 살펴보자.
local_1c와 local164는 CreateProcessA()에서 사용되고 local_164는 문자열의 포인터, local_1c는 PROCESS_INFORMATION 구조체 (16바이트)인 것을 알 수 있다.
local_60은 GetStartupInfoA()에서 사용되고 STARTUPINFO 구조체(68바이트)인 것을 알 수 있다.
※ 크기는 모두 32비트 기준이다.
구조체에서 우클릭 - Edit Data Type을 선택해 보자.
구조체의 구성 정보를 모두 확인 할 수 있다.
그리고 마지막 부분에 Base of Code 함수인 FUN_00401000에 대한 상호 참조가 3개 있다.
이것은 0040011c, 004001f4, 그리고 __scrt_common_main_seh 함수의 004013ae 위치에서 FUN_00401000 함수가 호출되거나 사용된다는 것을 의미한다.
Listing 윈도우에서 툴바의 Edit the Listing fields 버튼을 클릭하면 여러가지 상황에서의 필드를 조정하거나 수정할 수 있다. 위 그림의 경우 Instruction/Data의 필드를 표시하고 있다. 마우스 오른쪽 버튼을 클릭하면 다른 필드를 추가하거나 삭제 할 수 있다.
리버스 엔지니어링 기드라 실전 가이드 p.142 오타 수정:
FUN_004010a0 함수의 제2인수(param_2)는 구조체의 세 번째 멤버 변수가 지정되었습니다. 주소 0x00418000을 선두로 하는 구조체의 경우 세 번째 멤버 변수인 0x00418008에 0x1a가 FUN_004010a0 함수의 제2인수가 됩니다.
Set Equate 명령은 1Ah 값 위에서 우클릭해야 표시된다.
※ SHGetSpecialFolderPath()에서 세 번째 인수에 0x1a가 들어갔을때의 의미:
CSIDL_APPDATA = 0x1A(26) The file system directory that serves as a common repository for application-specific data.
Application Data(파일 시스템 디렉토리)
리버스 엔지니어링 기드라 실전 가이드 p.145 참고:
FUN_004010a0() - FUN_00401140() - FUN_00401180() - FUN_004011a0() 까지 들어가면 vsprintfg() 호출 명령이 있다.
리버스 엔지니어링 기드라 실전 가이드 p.147 오타 수정:
download_file 함수의 FUN_004010a0 함수 호출원을 디스어셈블한 결과를 Listing 창에서 확인해 보겠습니다. FUN_004010a0함수 호출 이전에는 함수 선두에 있는 EBP 대피 처리를 제외하고 3개의 PUSH 명령이 있습니다. 주소 0x004010e8에서 PUSH되는 값은 디컴파일 결과에는 반영되어 있지 않았습니다.
FUN_004010a0()에 세 번째 인수(void *)는 위와 같이 추가한다.
리버스 엔지니어링 기드라 실전 가이드 p.148 참고:
구조체의 이름과 멤버 변수명을 바꿔주면 그 구조체가 사용된 함수들에서 함수의 파라미터로 전달된 구조체 이름이 자동으로 바뀌는 것처럼 설명되고 그림으로 표시되는데, 함수의 파라미터 이름은 모두 일일이 우클릭 - Rename Variable 명령으로 바꿔줘야 한다. 함수 이름, 구조체 멤버 변수 이름 등이 표시되는 부분은 수정시 자동으로 바뀐다.
또, 책을 따라 진행하고 나면 p.149의 예제 3-16 코드 부분에 나온 것보다는 보기 편하게 결과가 나온다.
예) download_file()의 파라미터 이름을 바꾸고 나면 3-16 코드에서 표시된 내부 코드 중 make_path(buf, conf->field_0x8, ...); 같은 부분에서 conf->field_0x8은 실제로는 conf->CSIDL로 보기 좋게 표시된다.
이 결과는 0x100e00 주소에 있는 64바이트 문자열 b9V12dPGtk7BKZUD/NJeX4vxjIcERzH+pQgT5iwYAlMyCWOFfnr3Soq06L8hamsu의 첫 글자가 'b'라는 것과 각 문자의 10진수 ASCII CODE를 의미한다.
그 아래 명령...
b64_custom_table = "".join([chr(b) for b in b64_custom_table_array])
b64_custom_table
의 결과가... 'b9V12dPGtk7BKZUD/NJeX4vxjIcERzH+pQgT5iwYAlMyCWOFfnr3Soq06L8hamsu'
인 것을 통해서도 알 수 있다.
리버스 엔지니어링 기드라 실전 가이드 p.279 참고:
def list_xrefs_call_functions(func_name):
manager = currentProgram.getFunctionManager()
for func in manager.getFunctions(True):
if func.getName() in func:
for xref in getReferencesTo(func.getEntryPoint()):
if xref.getReferenceType().toString() == 'UNCONDITIONAL_CALL':
print('{} is called at {}'.format(func.getName(), xref, getFromAddress()))
dangerous_func_names = ['getpw', 'gets', 'sprintf', 'strcat', 'strcpy', 'vsprintf']
list_xrefs_call_functions(dangerous_func_names)
위 함수 전체를 그대로 갖다 붙여넣기 하면 안된다. 한 줄씩 복사해서 붙여 넣어야 한다.
Jython에서 실행하면 위와 같은 에러가 발생한다. FunctionDB 객체가 반복 가능하지 않다는데 어떻게 해야 할까?