mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-29 00:24: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==5.15.10
|
||||||
PyQt5-Qt5==5.15.2
|
PyQt5-Qt5==5.15.2
|
||||||
webviewpy==1.3.0
|
webviewpy==1.3.0
|
||||||
pefile
|
|
||||||
tinycss2
|
tinycss2
|
@ -1,5 +1,4 @@
|
|||||||
PyQt6==6.7.0
|
PyQt6==6.7.0
|
||||||
PyQt6-Qt6==6.7.0
|
PyQt6-Qt6==6.7.0
|
||||||
webviewpy==1.3.0
|
webviewpy==1.3.0
|
||||||
pefile
|
|
||||||
tinycss2
|
tinycss2
|
@ -1,7 +1,7 @@
|
|||||||
import modulefinder, shutil, os, sys, pefile
|
import modulefinder, shutil, os, sys
|
||||||
import builtins, platform
|
import builtins, platform
|
||||||
import sys
|
import sys
|
||||||
|
from importanalysis import importanalysis
|
||||||
pyversion = platform.python_version()
|
pyversion = platform.python_version()
|
||||||
pyversion2 = "".join(pyversion.split(".")[:2])
|
pyversion2 = "".join(pyversion.split(".")[:2])
|
||||||
x86 = platform.architecture()[0] == "32bit"
|
x86 = platform.architecture()[0] == "32bit"
|
||||||
@ -222,31 +222,15 @@ for f in collect:
|
|||||||
if f.endswith(".pyc") or f.endswith("Thumbs.db"):
|
if f.endswith(".pyc") or f.endswith("Thumbs.db"):
|
||||||
os.remove(f)
|
os.remove(f)
|
||||||
elif f.endswith(".exe") or f.endswith(".pyd") or f.endswith(".dll"):
|
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"):
|
if f.endswith("Magpie.Core.exe"):
|
||||||
continue
|
continue
|
||||||
if f.endswith("QtWidgets.pyd"):
|
imports=importanalysis(f)
|
||||||
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
|
|
||||||
print(f, imports)
|
print(f, imports)
|
||||||
if len(imports) == 0:
|
if len(imports) == 0:
|
||||||
continue
|
continue
|
||||||
with open(f, "rb") as ff:
|
with open(f, "rb") as ff:
|
||||||
bs = bytearray(ff.read())
|
bs = bytearray(ff.read())
|
||||||
for _dll in imports:
|
for _dll,offset in imports:
|
||||||
if _dll.lower().startswith("api-ms-win-core"):
|
if _dll.lower().startswith("api-ms-win-core"):
|
||||||
# 其实对于api-ms-win-core-winrt-XXX实际上是到ComBase.dll之类的,不过此项目中不包含这些
|
# 其实对于api-ms-win-core-winrt-XXX实际上是到ComBase.dll之类的,不过此项目中不包含这些
|
||||||
_target = "kernel32.dll"
|
_target = "kernel32.dll"
|
||||||
@ -254,9 +238,8 @@ for f in collect:
|
|||||||
_target = "ucrtbase.dll"
|
_target = "ucrtbase.dll"
|
||||||
_dll = _dll.encode()
|
_dll = _dll.encode()
|
||||||
_target = _target.encode()
|
_target = _target.encode()
|
||||||
idx = bs.find(_dll)
|
|
||||||
# print(len(bs))
|
# 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))
|
# print(len(bs))
|
||||||
with open(f, "wb") as ff:
|
with open(f, "wb") as ff:
|
||||||
ff.write(bs)
|
ff.write(bs)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user