03 DLL 디스어셈블러 만들기
원문 : http://kkamagui.springnote.com/pages/388049
들어가기 전에...
- 이 글은 kkamagui에 의해 작성된 글입니다.
- 마음껏 인용하시거나 사용하셔도 됩니다. 단 출처(http://kkamagui.tistory.com, http://kkamagui.springnote.com)는 밝혀 주십시오.
- 기타 사항은 mint64os at gmail.com 이나 http://kkamagui.tistory.com으로 보내주시면 반영하겠습니다.
- 상세한 내용은 책 "64비트 멀티코어 OS 구조와 원리"를 참고하기 바랍니다.
항상 분석을 하면 노가다가 많고 일일이 손으로 클릭을 해가면서 또는 눈으로 찾아가면서 분석을 해야 했다. 내가 원체 UI에 별로 관심이 없다보니 UI의 수준은 당연 극악의 콘솔형태... 물론 생긴건 GUI다.(그만큼 UI가 엉망이라는.... ㅡ_ㅡ;;;). 언젠가 한번 DLL 분석 툴을 파이썬으로 만들면 재미있겠다고 생각했는데... 파이썬용 디스어셈블러 자료는 찾아놓고 실제로 DLL을 파이썬으로 당겨야 하는데 엄두가 나지 않았다.
오늘 잠시 짬을 내서 일하다 잠도 안자고 해봤는데, 의외로 C 함수를 쓰는게 간단하다.
DLL 및 C 타입의 변수 등등의 사용
DLL을 로드해서 사용하는 코드를 C로 만들면 LoadLibrary() 함수를 호출하고 다시 GetProcAddress()를 호출하면 된다. 파이썬에서는 이것을 어떻게 할까? 블로그를 찾아보고 파이썬 마을을 둘러봤더니 ctypes라는 것이 보였다. Python 2.5 버전에서 표준 라이브러리에 포함되어있는 라이브러리라는데, 상당히 C 스타일 적이다.(아래는 Python 문서에 포함된 예제이다.)
- >>> from ctypes import *
>>> print windll.kernel32 - <WinDLL 'kernel32', handle ... at ...>
>>> print cdll.msvcrt - <CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt
windll에 보면 kernel32.dll, gdi32.dll 등등의 DLL의 정보를 포함하는 모듈이 들어있음을 알 수 있다. C 런타임 라이브러리도 사용할 수 있는데, cdll.msvcrt를 모듈을 이용하면 C 라이브러리를 사용할 수 있다.
- >>> from ctypes import *
>>> libc.printf
<_FuncPtr object at 0x...>
>>> print windll.kernel32.GetModuleHandleA - <_FuncPtr object at 0x...>
재미있는 부분은 포인터도 사용할 수 있다는 것이다.(크아... 이제 완전 게임 끝났다.. @0@)/~ 이렇게 좋을 수가.. ㅜ_ㅜ)
- >>> from ctypes import *
>>> i = c_int(42)
>>> pi = pointer(i)
>>> pi.contents
c_long(42)
더 자세한 사항은 파이썬 도움말을 참고하도록 하자.
디스어셈블러(Disassember) 모듈
디스어셈블러 모듈은 파이썬 용으로 따로 개발된게 있다.(어찌나 다행인지.. ㅡ_ㅡ;;; 내가 가지고 있는걸로 파이썬에 붙일려고 했는데, 이렇게 되면 기절한다... ㅡ_ㅡ;;;)
http://www.ragestorm.net/distorm/ 사이트에 가면 파이썬용 모듈을 받을 수 있고 간단히 pyd파일을 받아서 파이썬이 설치된 Lib 폴더에 넣기만 하면 편하게 사용할 수 있다. 아래는 위 홈페이지에서 설명해 놓은 사용 예제이다.
- Note: Save the file in %PYTHONDIR%\Lib\site-packages\
from distorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits
l = Decode(0x100, open("file.com", "rb").read(), Decode16Bits)
for i in l:
print "0x%08x (%02x) %-20s %s" % (i[0], i[1], i[3], i[2])
디스어셈블러 작성
이제 디스어셈블러를 작성할 준비가 모두 끝났다. 이제 이 모듈들을 이용하여 kernel32.dll에 있는 OpenProcess 함수를 디스어셈블리해보자.
- # -*- coding: cp949 -*-
from distorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits
# c관련 함수를 사용하기위해 처리
from ctypes import *
import ctypes - # c 런타임 라이브러리를 가지고 있음
libc = cdll.msvcrt;
# kernel32.dll을 여는 여러 방법
#kernel32 = windll.kernel32;
kernel32 = windll.LoadLibrary( 'kernel32.dll' ); - # OpenProcess를 얻는다.
openProcessAddress = kernel32.GetProcAddress( kernel32._handle, "OpenProcess" ); - # 버퍼를 할당해서 디스어셈블리를 하기위해 버퍼에 넣는다.
buf = ctypes.c_buffer( 4096 );
libc.memcpy( buf, openProcessAddress, 4096 );
#libc.memcpy( buf, 0x7c809b96, 4096 ); - l = Decode(openProcessAddress, buf, Decode32Bits)
for i in l:
# 아래와 같은 형식으로 출력된다.
# 0x7c8309e1 (02) 8bff MOV EDI, EDI
print "0x%08X (%02X) %-20s %s" % (i[0], i[1], i[3].upper(), i[2])
소스 코드는 위와 같이 아주 간단하다. 출력 결과는 아래와 같이 깔끔하게 나온다.
0x7C8309E1 (02) 8BFF MOV EDI, EDI
0x7C8309E3 (01) 55 PUSH EBP
0x7C8309E4 (02) 8BEC MOV EBP, ESP
0x7C8309E6 (03) 83EC 20 SUB ESP, 0x20
0x7C8309E9 (03) 8B45 10 MOV EAX, [EBP+0x10]
0x7C8309EC (03) 8945 F8 MOV [EBP-0x8], EAX
0x7C8309EF (03) 8B45 0C MOV EAX, [EBP+0xc]
0x7C8309F2 (01) 56 PUSH ESI
정말 멋지다.. ㅜ_ㅜ... 이렇게 몇줄 작성하지 않았는데 이런 결과가 나오다니... ㅡ_ㅜ... 정말 환상적이지 않을 수 없다. ㅜ_ㅜ...
파이썬 만쉐이.. ㅜ_ㅜ...
첨부
- distorm.pyd : 디스어셈블리 라이브러리
TODO
- 코드 내부에 있는 Jump 및 Call 관련 루틴을 따라가서 분석하는 기능 추가하기
이 글은 스프링노트에서 작성되었습니다.
'프로그래밍(Programming) > 파이썬(Python)' 카테고리의 다른 글
하드디스크를 돌면서 특정한 확장자를 가진 파일을 지워주는 코드 (0) | 2007.12.22 |
---|---|
Python 공부에 도움이 되는 사이트~!!! PDF 파일 무료제공~ ^ㅡ^ (4) | 2007.11.22 |
파이썬(Python)으로 GPU 컨트롤하기 (0) | 2007.11.16 |
04 진보된 DLL 디스어셈블러 만들기 (0) | 2007.11.14 |
01 이글루스에서 덧글 뽑기 (0) | 2007.11.14 |