mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-28 08:04:13 +08:00
pe
This commit is contained in:
parent
6d640336b1
commit
8a6181861a
233
LunaTranslator/importanalysis.py
Normal file
233
LunaTranslator/importanalysis.py
Normal file
@ -0,0 +1,233 @@
|
||||
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_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
|
||||
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
|
||||
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
|
||||
)
|
||||
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
|
@ -1,5 +1,4 @@
|
||||
PyQt5==5.15.10
|
||||
PyQt5-Qt5==5.15.2
|
||||
webviewpy==1.3.0
|
||||
pefile
|
||||
tinycss2
|
@ -1,5 +1,4 @@
|
||||
PyQt6==6.7.0
|
||||
PyQt6-Qt6==6.7.0
|
||||
webviewpy==1.3.0
|
||||
pefile
|
||||
tinycss2
|
@ -1,7 +1,7 @@
|
||||
import modulefinder, shutil, os, sys, pefile
|
||||
import modulefinder, shutil, os, sys
|
||||
import builtins, platform
|
||||
import sys
|
||||
|
||||
from importanalysis import importanalysis
|
||||
pyversion = platform.python_version()
|
||||
pyversion2 = "".join(pyversion.split(".")[:2])
|
||||
x86 = platform.architecture()[0] == "32bit"
|
||||
@ -222,31 +222,15 @@ for f in collect:
|
||||
if f.endswith(".pyc") or f.endswith("Thumbs.db"):
|
||||
os.remove(f)
|
||||
elif f.endswith(".exe") or f.endswith(".pyd") or f.endswith(".dll"):
|
||||
|
||||
try:
|
||||
pe = pefile.PE(f)
|
||||
import_table = pe.DIRECTORY_ENTRY_IMPORT
|
||||
imports = []
|
||||
for entry in import_table:
|
||||
if entry.dll.decode("utf-8").lower().startswith("api"):
|
||||
imports.append(entry.dll.decode("utf-8"))
|
||||
pe.close()
|
||||
except:
|
||||
continue
|
||||
if f.endswith("Magpie.Core.exe"):
|
||||
continue
|
||||
if f.endswith("QtWidgets.pyd"):
|
||||
imports += [
|
||||
"api-ms-win-crt-runtime-l1-1-0.dll",
|
||||
"api-ms-win-crt-heap-l1-1-0.dll",
|
||||
]
|
||||
# pefile好像有bug,仅对于QtWidgets.pyd这个文件,只能读取到导入了Qt5Widgets.dll
|
||||
imports=importanalysis(f)
|
||||
print(f, imports)
|
||||
if len(imports) == 0:
|
||||
continue
|
||||
with open(f, "rb") as ff:
|
||||
bs = bytearray(ff.read())
|
||||
for _dll in imports:
|
||||
for _dll,offset in imports:
|
||||
if _dll.lower().startswith("api-ms-win-core"):
|
||||
# 其实对于api-ms-win-core-winrt-XXX实际上是到ComBase.dll之类的,不过此项目中不包含这些
|
||||
_target = "kernel32.dll"
|
||||
@ -254,9 +238,8 @@ for f in collect:
|
||||
_target = "ucrtbase.dll"
|
||||
_dll = _dll.encode()
|
||||
_target = _target.encode()
|
||||
idx = bs.find(_dll)
|
||||
# print(len(bs))
|
||||
bs[idx : idx + len(_dll)] = _target + b"\0" * (len(_dll) - len(_target))
|
||||
bs[offset : offset + len(_dll)] = _target + b"\0" * (len(_dll) - len(_target))
|
||||
# print(len(bs))
|
||||
with open(f, "wb") as ff:
|
||||
ff.write(bs)
|
||||
|
Loading…
x
Reference in New Issue
Block a user