저는 회사에서 대부분의 분석 업무를 "윈도우7" 환경에서 진행합니다.
( 단순히 XP 에 비해서 Win7 이 조금 더 손에 익었다는 이유로..;;; )
윈도우7 에서 DLL 파일을 분석할 때,
올리디버거로 열고 한 번만 로딩해서 분석이 완료되면 상관없지만...
어떤 파일들은 크래쉬 등의 이유로 여러번 로딩을 해야하는 경우도 간혹 있습니다.
이때 해당 DLL 파일에 DYNAMIC_BASE 옵션이 적용되어 있다면...
심히 피곤해질 수도 있는데요...;;;
가령 분석자료를 작성하기 위해 DLL 의 디스어셈블 코드를 캡쳐하면서...
분석을 하고 있는데 크래쉬가 발생해서 DLL 을 다시 로딩했다..;;
이러면 조금전까지 캡쳐해둔 DLL 의 주소와 새로 로딩된 주소가 달라져서...
살포시 멘.붕(까지는 아니려나요..?)이 올 수도 있습니다.
어제군요...
게임 해킹툴 DLL 파일 하나를 분석하면서 열심히 코드 복사해가며..
분석자료를 정리하던 중에 크래쉬가 발생한 바람에...;;;
분석자료에 기록된 그 번지에 DLL 이 로딩될 때까지...
DLL 로딩만 수십번하는 뻘짓을 했습니다;;;;
뻘짓을 하는 도중에 '귀차니즘' 이 스믈스믈 발동되면서...
아!!! DLL 파일의 이미지 베이스를 내가 보던 그 주소로 지정하고...
DYNAMIC_BASE 옵션을 제거하면 되겠구나~!! @_@
하는 생각을 하고는 정말 단순하게 이미지 베이스랑 DYNAMIC_BASE 옵션만 수정하고...
다시 DLL 을 로딩하려는데... 이게 왠걸..? 일부 코드가 희안하게 깨져서 나오더군요..
이미지 베이스 값만 바뀌었을뿐 재배치 정보들은 여전히 이전 베이스 주소를 기준으로 되어 있어서...
문제가 된거였습니다...
결국 재배치 정보들도 새로운 이미지 베이스 값에 맞게 바꿔줘야겠구나 싶어서...
머리를 한참 굴리다가 파이썬으로 만들어 봤습니다..
# PE Rebase tool
import sys
import pefile
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x40
def main():
if len(sys.argv) != 3:
print "# [ PE Rebase Tool ] #\n"
print "Usage : rebase.py [Target PE File] [New Base Address]"
else:
pe = pefile.PE(sys.argv[1])
curBaseAddr = pe.OPTIONAL_HEADER.ImageBase;
newBaseAddr = int(sys.argv[2], 0)
print "# Target File : " + sys.argv[1]
print "# Current Base Address : 0x%X" % (curBaseAddr)
print "# -> New Base Address : 0x%X" % (newBaseAddr)
# ImageBase
pe.OPTIONAL_HEADER.ImageBase = newBaseAddr
# DLL Characteristics : IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE off
pe.OPTIONAL_HEADER.DllCharacteristics = pe.OPTIONAL_HEADER.DllCharacteristics & ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
# Relocation Information
pe.parse_data_directories()
for relocTbl in pe.DIRECTORY_ENTRY_BASERELOC:
print "-----------------------------------------------------------------------"
print "@ RVA : %X, (Size : %X)" % (relocTbl.struct.VirtualAddress, relocTbl.struct.SizeOfBlock)
print "-----------------------------------------------------------------------"
reloc = relocTbl.entries
for idx in reloc:
reloc_offset = idx.rva - idx.base_rva
if reloc_offset != 0:
curAddr = pe.get_dword_at_rva(idx.rva)
newAddr = curAddr - curBaseAddr + newBaseAddr
print "[0x%X] : %X ==> %X" % (idx.rva, curAddr, newAddr)
pe.set_dword_at_rva(idx.rva, newAddr)
pe.write(filename = sys.argv[1] + ".patched")
if __name__ == "__main__":
sys.exit(main())
이번에 파이썬을 처음 건드려본건데...
제대로 알고 활용만 잘하면 정말 편하겠구나~~ @_@ 하는 생각이 확~~ 들더군요 ㅎㅎㅎㅎ
본격적으로 파이썬도 익혀봐야겠습니다... :))
ps...
잘모르는 파이썬 문법 익혀가며 시간 투자해서 스크립트 다 짰는데..;;;
editbin 툴이 있었다는걸 뒤늦게 떠올린게 함정...ㅠㅠ...
하아... =3=3=3