LunaTranslator/.github/scripts/importanalysis.py

244 lines
7.2 KiB
Python
Raw Normal View History

2024-06-25 19:49:49 +08:00
from ctypes import (
c_size_t,
windll,
memmove,
Structure,
c_uint64,
cast,
POINTER,
sizeof,
c_char_p,
)
from ctypes.wintypes import LPVOID, DWORD, WORD, LONG, BYTE
ULONGLONG = c_uint64
kernel32 = windll.kernel32
VirtualAlloc = kernel32.VirtualAlloc
VirtualAlloc.argtypes = LPVOID, c_size_t, DWORD, DWORD
VirtualAlloc.restype = LPVOID
VirtualFree = kernel32.VirtualFree
VirtualFree.argtypes = LPVOID, c_size_t, DWORD
class IMAGE_DOS_HEADER(Structure):
_fields_ = [("_nouse", WORD * 30), ("e_lfanew", LONG)]
class IMAGE_FILE_HEADER(Structure):
_fields_ = [
("Machine", WORD),
("NumberOfSections", WORD),
("TimeDateStamp", DWORD),
("PointerToSymbolTable", DWORD),
("NumberOfSymbols", DWORD),
("SizeOfOptionalHeader", WORD),
("Characteristics", WORD),
]
class IMAGE_DATA_DIRECTORY(Structure):
_fields_ = [
("VirtualAddress", DWORD),
("Size", DWORD),
]
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
class IMAGE_OPTIONAL_HEADER32(Structure):
_fields_ = [
("Magic", WORD),
("MajorLinkerVersion", BYTE),
("MinorLinkerVersion", BYTE),
("SizeOfCode", DWORD),
("SizeOfInitializedData", DWORD),
("SizeOfUninitializedData", DWORD),
("AddressOfEntryPoint", DWORD),
("BaseOfCode", DWORD),
("BaseOfData", DWORD),
("ImageBase", DWORD),
("SectionAlignment", DWORD),
("FileAlignment", DWORD),
("MajorOperatingSystemVersion", WORD),
("MinorOperatingSystemVersion", WORD),
("MajorImageVersion", WORD),
("MinorImageVersion", WORD),
("MajorSubsystemVersion", WORD),
("MinorSubsystemVersion", WORD),
("Win32VersionValue", DWORD),
("SizeOfImage", DWORD),
("SizeOfHeaders", DWORD),
("CheckSum", DWORD),
("Subsystem", WORD),
("DllCharacteristics", WORD),
("SizeOfStackReserve", DWORD),
("SizeOfStackCommit", DWORD),
("SizeOfHeapReserve", DWORD),
("SizeOfHeapCommit", DWORD),
("LoaderFlags", DWORD),
("NumberOfRvaAndSizes", DWORD),
("DataDirectory", IMAGE_DATA_DIRECTORY * IMAGE_NUMBEROF_DIRECTORY_ENTRIES),
]
class IMAGE_OPTIONAL_HEADER64(Structure):
_fields_ = [
("Magic", WORD),
("MajorLinkerVersion", BYTE),
("MinorLinkerVersion", BYTE),
("SizeOfCode", DWORD),
("SizeOfInitializedData", DWORD),
("SizeOfUninitializedData", DWORD),
("AddressOfEntryPoint", DWORD),
("BaseOfCode", DWORD),
("ImageBase", ULONGLONG),
("SectionAlignment", DWORD),
("FileAlignment", DWORD),
("MajorOperatingSystemVersion", WORD),
("MinorOperatingSystemVersion", WORD),
("MajorImageVersion", WORD),
("MinorImageVersion", WORD),
("MajorSubsystemVersion", WORD),
("MinorSubsystemVersion", WORD),
("Win32VersionValue", DWORD),
("SizeOfImage", DWORD),
("SizeOfHeaders", DWORD),
("CheckSum", DWORD),
("Subsystem", WORD),
("DllCharacteristics", WORD),
("SizeOfStackReserve", ULONGLONG),
("SizeOfStackCommit", ULONGLONG),
("SizeOfHeapReserve", ULONGLONG),
("SizeOfHeapCommit", ULONGLONG),
("LoaderFlags", DWORD),
("NumberOfRvaAndSizes", DWORD),
("DataDirectory", IMAGE_DATA_DIRECTORY * IMAGE_NUMBEROF_DIRECTORY_ENTRIES),
]
class IMAGE_NT_HEADERS32(Structure):
_fields_ = [
("_nouse", DWORD),
("FileHeader", IMAGE_FILE_HEADER),
("OptionalHeader", IMAGE_OPTIONAL_HEADER32),
]
class IMAGE_NT_HEADERS64(Structure):
_fields_ = [
("_nouse", DWORD),
("FileHeader", IMAGE_FILE_HEADER),
("OptionalHeader", IMAGE_OPTIONAL_HEADER64),
]
IMAGE_SIZEOF_SHORT_NAME = 8
class IMAGE_SECTION_HEADER(Structure):
_fields_ = [
("Name", BYTE * IMAGE_SIZEOF_SHORT_NAME),
("VirtualSize", DWORD),
("VirtualAddress", DWORD),
("SizeOfRawData", DWORD),
("PointerToRawData", DWORD),
("PointerToRelocations", DWORD),
("PointerToLinenumbers", DWORD),
("NumberOfRelocations", WORD),
("NumberOfLinenumbers", WORD),
("Characteristics", DWORD),
]
MEM_COMMIT = 0x00001000
MEM_DECOMMIT = 0x00004000
PAGE_READWRITE = 0x04
IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10B
2024-06-25 20:16:57 +08:00
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20B
2024-06-25 19:49:49 +08:00
IMAGE_DIRECTORY_ENTRY_IMPORT = 1
class IMAGE_IMPORT_DESCRIPTOR(Structure):
_fields_ = [
("OriginalFirstThunk", DWORD),
("TimeDateStamp", DWORD),
("ForwarderChain", DWORD),
("Name", DWORD),
("FirstThunk", DWORD),
]
def Rva2Offset(rva, psh, pnt, IMAGE_NT_HEADERS):
pSeh = psh
psh = cast(psh, POINTER(IMAGE_SECTION_HEADER))
pnt = cast(pnt, POINTER(IMAGE_NT_HEADERS))
for i in range(pnt.contents.FileHeader.NumberOfSections):
pSeh1 = cast(pSeh, POINTER(IMAGE_SECTION_HEADER)).contents
if (
rva >= pSeh1.VirtualAddress
and rva < pSeh1.VirtualAddress + pSeh1.VirtualSize
):
break
pSeh += sizeof(IMAGE_SECTION_HEADER)
pSeh = cast(pSeh, POINTER(IMAGE_SECTION_HEADER)).contents
2024-06-25 20:16:57 +08:00
if pSeh.VirtualAddress == 0 or pSeh.PointerToRawData == 0:
return -1
2024-06-25 19:49:49 +08:00
return rva - pSeh.VirtualAddress + pSeh.PointerToRawData
def importanalysis(fname):
with open(fname, "rb") as ff:
bs = ff.read()
virtualpointer = VirtualAlloc(None, len(bs), MEM_COMMIT, PAGE_READWRITE)
memmove(virtualpointer, bs, len(bs))
ntheaders_addr = (
virtualpointer
+ cast(virtualpointer, POINTER(IMAGE_DOS_HEADER)).contents.e_lfanew
)
ntheaders = cast(ntheaders_addr, POINTER(IMAGE_NT_HEADERS32)).contents
IMAGE_NT_HEADERS = IMAGE_NT_HEADERS32
magic = ntheaders.OptionalHeader.Magic
if magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC:
ntheaders = cast(ntheaders_addr, POINTER(IMAGE_NT_HEADERS64)).contents
IMAGE_NT_HEADERS = IMAGE_NT_HEADERS64
2024-06-25 20:16:57 +08:00
magic = ntheaders.OptionalHeader.Magic
if magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC:
# 无效的文件
return []
2024-06-25 19:49:49 +08:00
pSech = (
ntheaders_addr
+ sizeof(DWORD)
+ sizeof(IMAGE_FILE_HEADER)
+ ntheaders.FileHeader.SizeOfOptionalHeader
)
pImportDescriptor = virtualpointer + Rva2Offset(
ntheaders.OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress,
pSech,
ntheaders_addr,
IMAGE_NT_HEADERS,
)
pImportDescriptor_data = cast(
pImportDescriptor, POINTER(IMAGE_IMPORT_DESCRIPTOR)
).contents
collect = []
while pImportDescriptor_data.Name:
offset = Rva2Offset(
pImportDescriptor_data.Name, pSech, ntheaders_addr, IMAGE_NT_HEADERS
)
2024-06-25 20:16:57 +08:00
if offset == -1:
# python3.dll无导入
return []
2024-06-25 19:49:49 +08:00
name = virtualpointer + offset
collect.append((cast(name, c_char_p).value.decode(), offset))
pImportDescriptor += sizeof(IMAGE_IMPORT_DESCRIPTOR)
pImportDescriptor_data = cast(
pImportDescriptor, POINTER(IMAGE_IMPORT_DESCRIPTOR)
).contents
VirtualFree(virtualpointer, len(bs), MEM_DECOMMIT)
return collect