LunaTranslator/.github/scripts/importanalysis.py
恍兮惚兮 8e37d6dc64 scripts
2024-11-08 17:07:24 +08:00

244 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20B
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
if pSeh.VirtualAddress == 0 or pSeh.PointerToRawData == 0:
return -1
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
magic = ntheaders.OptionalHeader.Magic
if magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC:
# 无效的文件
return []
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
)
if offset == -1:
# python3.dll无导入
return []
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