This commit is contained in:
HIllya51 2024-01-12 23:57:29 +08:00
parent 34e05da0fa
commit 75713f8322
32 changed files with 331 additions and 1003 deletions

View File

@ -293,7 +293,7 @@ class MAINUI() :
self.refresh_on_get_trans_signature=_showrawfunction_sig self.refresh_on_get_trans_signature=_showrawfunction_sig
_showrawfunction() _showrawfunction()
if currentsignature==self.currentsignature: if currentsignature==self.currentsignature and globalconfig['showfanyi']:
self.translation_ui.displayres.emit(globalconfig['fanyi'][classname]['name'],globalconfig['fanyi'][classname]['color'],res,onlytrans) self.translation_ui.displayres.emit(globalconfig['fanyi'][classname]['name'],globalconfig['fanyi'][classname]['color'],res,onlytrans)
if embedcallback: if embedcallback:

View File

@ -1,7 +1,13 @@
baseobject=None baseobject=None
from traceback import print_exc from traceback import print_exc
import io,sys import io,sys,platform,os
isbit64= platform.architecture()[0]=='64bit'
DLL3264path=os.path.abspath('files/plugins/DLL'+('32','64')[isbit64])
def GetDllpath(_):
if isinstance(_,str):
return os.path.join(DLL3264path,_)
elif isinstance(_,(list,tuple)):
return os.path.join(DLL3264path,_[isbit64])
class debugoutput(io.IOBase): class debugoutput(io.IOBase):
def __init__(self,idx,file=sys.stdout) -> None: def __init__(self,idx,file=sys.stdout) -> None:
super().__init__() super().__init__()

View File

@ -304,6 +304,7 @@ class hookselect(closeashidewindow):
self.allres=OrderedDict() self.allres=OrderedDict()
self.hidesearchhookbuttons() self.hidesearchhookbuttons()
def addnewhook(self,ss ,select,textthread): def addnewhook(self,ss ,select,textthread):
hc,hn,tp=textthread
if len(self.save)==0: if len(self.save)==0:
if gobject.baseobject.textsource.allow_set_text_name: if gobject.baseobject.textsource.allow_set_text_name:
self.ttCombomodelmodel.setHorizontalHeaderLabels(_TRL(['显示','类型','HOOK','文本'])) self.ttCombomodelmodel.setHorizontalHeaderLabels(_TRL(['显示','类型','HOOK','文本']))
@ -354,8 +355,8 @@ class hookselect(closeashidewindow):
label.setStyleSheet("background-color: rgba(255, 255, 255, 0)") label.setStyleSheet("background-color: rgba(255, 255, 255, 0)")
checkbtn=QPushButton() checkbtn=QPushButton()
checkbtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) checkbtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
def _t(): def _t(tp):
_isusing=gobject.baseobject.textsource.checkisusingembed(textthread[0].tp.addr,textthread[0].tp.ctx,textthread[0].tp.ctx2) _isusing=gobject.baseobject.textsource.checkisusingembed(tp.addr,tp.ctx,tp.ctx2)
if _isusing: if _isusing:
_text='取消内嵌翻译' _text='取消内嵌翻译'
checkifnewgame(gobject.baseobject.textsource.pname) checkifnewgame(gobject.baseobject.textsource.pname)
@ -371,21 +372,21 @@ class hookselect(closeashidewindow):
_text="使用内嵌翻译" _text="使用内嵌翻译"
checkbtn.setText(''+_TR(_text)+'') checkbtn.setText(''+_TR(_text)+'')
return _isusing return _isusing
_t() _t(tp)
def _c(_): def _c(hc,tp,_):
gobject.baseobject.textsource.useembed(textthread[0].tp.addr,textthread[0].tp.ctx,textthread[0].tp.ctx2,not _t()) gobject.baseobject.textsource.useembed(tp.addr,tp.ctx,tp.ctx2,not _t(tp))
_use=_t() _use=_t(tp)
if _use: if _use:
savehook_new_data[gobject.baseobject.textsource.pname]['embedablehook'].append([textthread[0].hpcode,textthread[0].tp.addr,textthread[0].tp.ctx,textthread[0].tp.ctx2]) savehook_new_data[gobject.baseobject.textsource.pname]['embedablehook'].append([hc,tp.addr,tp.ctx,tp.ctx2])
else: else:
save=[] save=[]
for _ in savehook_new_data[gobject.baseobject.textsource.pname]['embedablehook']: for _ in savehook_new_data[gobject.baseobject.textsource.pname]['embedablehook']:
hc,ad,c1,c2=_ hc,ad,c1,c2=_
if(hc,ad,c1,c2)==(textthread[0].hpcode,textthread[0].tp.addr,textthread[0].tp.ctx,textthread[0].tp.ctx2): if(hc,ad,c1,c2)==(hc,tp.addr,tp.ctx,tp.ctx2):
save.append(_) save.append(_)
for _ in save: for _ in save:
savehook_new_data[gobject.baseobject.textsource.pname]['embedablehook'].remove(_) savehook_new_data[gobject.baseobject.textsource.pname]['embedablehook'].remove(_)
checkbtn.clicked.connect(_c) checkbtn.clicked.connect(functools.partial(_c,hc,tp))
hlay.addWidget(checkbtn) hlay.addWidget(checkbtn)
colidx=2+(gobject.baseobject.textsource.allow_set_text_name) colidx=2+(gobject.baseobject.textsource.allow_set_text_name)
self.tttable.setIndexWidget(self.ttCombomodelmodel.index(rown,colidx),embedw) self.tttable.setIndexWidget(self.ttCombomodelmodel.index(rown,colidx),embedw)

View File

@ -28,7 +28,8 @@ def gethookgrid(self) :
[('文本缓冲区长度',5),(getspinbox(0,10000,globalconfig,'flushbuffersize',callback=lambda x:gobject.baseobject.textsource.setsettings()),3)], [('文本缓冲区长度',5),(getspinbox(0,10000,globalconfig,'flushbuffersize',callback=lambda x:gobject.baseobject.textsource.setsettings()),3)],
[('过滤包含乱码的文本行',5),(getsimpleswitch(globalconfig,'filter_chaos_code'),1),(getcolorbutton(globalconfig,'',icon='fa.gear',constcolor="#FF69B4",callback=lambda:codeacceptdialog(self)),1)], [('过滤包含乱码的文本行',5),(getsimpleswitch(globalconfig,'filter_chaos_code'),1),(getcolorbutton(globalconfig,'',icon='fa.gear',constcolor="#FF69B4",callback=lambda:codeacceptdialog(self)),1)],
[], [],
[('区分人名和文本',5),getsimpleswitch(globalconfig,'allow_set_text_name')] [('区分人名和文本',5),getsimpleswitch(globalconfig,'allow_set_text_name')],
[('使用YAPI注入',5),getsimpleswitch(globalconfig,'use_yapi')],
] ]

View File

@ -133,7 +133,7 @@ def setTabThree_lazy(self) :
[('显示日语注音',4),self.show_hira_switch,'',('注音颜色',4),getcolorbutton(globalconfig,'jiamingcolor',callback=lambda: selectcolor(self,globalconfig, "jiamingcolor", self.jiamingcolor_b),name='jiamingcolor_b',parent=self),'',('注音字体缩放',3),(getspinbox(0.05,1,globalconfig,'kanarate',double=True,step=0.05,dec=2),2)], [('显示日语注音',4),self.show_hira_switch,'',('注音颜色',4),getcolorbutton(globalconfig,'jiamingcolor',callback=lambda: selectcolor(self,globalconfig, "jiamingcolor", self.jiamingcolor_b),name='jiamingcolor_b',parent=self),'',('注音字体缩放',3),(getspinbox(0.05,1,globalconfig,'kanarate',double=True,step=0.05,dec=2),2)],
[('语法加亮',4 ),self.show_fenciswitch,'', [('语法加亮',4 ),self.show_fenciswitch,'',
('词性颜色(需要Mecab)',4), getcolorbutton(globalconfig,'',callback=lambda : multicolorset(self),icon='fa.gear',constcolor="#FF69B4") ,], ('词性颜色(需要Mecab)',4), getcolorbutton(globalconfig,'',callback=lambda : multicolorset(self),icon='fa.gear',constcolor="#FF69B4") ,],
[("显示翻译器名称",4),(getsimpleswitch(globalconfig ,'showfanyisource'),1)], [("显示翻译器名称",4),(getsimpleswitch(globalconfig ,'showfanyisource'),1),'',("显示翻译",4),(getsimpleswitch(globalconfig ,'showfanyi'),1)],
[('最长显示字数',4),(getspinbox(0,1000000,globalconfig,'maxoriginlength'),2)], [('最长显示字数',4),(getspinbox(0,1000000,globalconfig,'maxoriginlength'),2)],
[], [],

View File

@ -1,7 +1,7 @@
import platform,os import gobject,os
from ctypes import CDLL,c_void_p,c_int,c_char_p,c_long,cast,CFUNCTYPE,c_size_t,Structure,pointer,create_string_buffer,memmove,POINTER,c_char,c_int64,c_uint from ctypes import CDLL,c_void_p,c_int,c_char_p,c_long,cast,CFUNCTYPE,c_size_t,Structure,pointer,create_string_buffer,memmove,POINTER,c_char,c_int64,c_uint
curlpath=os.path.abspath(os.path.join('./files/plugins',['./libcurl-x64.dll','./libcurl.dll'][platform.architecture()[0]=='32bit'])) libcurl=CDLL(os.path.join(gobject.DLL3264path,('./libcurl.dll','./libcurl-x64.dll')[gobject.isbit64]))
libcurl=CDLL(curlpath)
CURL = c_void_p CURL = c_void_p
CURLSH=c_void_p CURLSH=c_void_p
class curl_slist(Structure): class curl_slist(Structure):

View File

@ -1,11 +1,8 @@
from ctypes import CDLL,c_size_t,c_void_p,POINTER,pointer,create_string_buffer from ctypes import CDLL,c_size_t,c_void_p,POINTER,pointer,create_string_buffer
import os,platform import os,gobject
_brotli=CDLL(gobject.GetDllpath('brotlicommon.dll'))
dllpath=os.path.abspath(os.path.join('./files/plugins/brotli',['./x64/brotlicommon.dll','./x86/brotlicommon.dll'][platform.architecture()[0]=='32bit'])) _brotli=CDLL(gobject.GetDllpath('brotlidec.dll'))
_brotli=CDLL(dllpath)
dllpath=os.path.abspath(os.path.join('./files/plugins/brotli',['./x64/brotlidec.dll','./x86/brotlidec.dll'][platform.architecture()[0]=='32bit']))
_brotli=CDLL(dllpath)
BrotliDecoderDecompress=_brotli.BrotliDecoderDecompress BrotliDecoderDecompress=_brotli.BrotliDecoderDecompress
BrotliDecoderDecompress.argtypes=c_size_t,c_void_p,POINTER(c_size_t),c_void_p BrotliDecoderDecompress.argtypes=c_size_t,c_void_p,POINTER(c_size_t),c_void_p
def decompress(data): def decompress(data):

View File

@ -7,15 +7,10 @@ import base64
from ocrengines.baseocrclass import baseocr from ocrengines.baseocrclass import baseocr
from ctypes import CDLL,c_char_p ,create_string_buffer,c_uint32,POINTER,c_int32 from ctypes import CDLL,c_char_p ,create_string_buffer,c_uint32,POINTER,c_int32
import os import os
import platform import gobject
class ocrwrapper: class ocrwrapper:
def __init__(self) -> None: def __init__(self) -> None:
self.dll=CDLL(gobject.GetDllpath(('ocr32.dll','ocr64.dll')))
if platform.architecture()[0]=='64bit':
bit='64'
else:
bit='32'
self.dll=CDLL(os.path.abspath('./files/plugins/ocr{}.dll'.format(bit)) )
def _OcrInit(self,szDetModel, szRecModel, szKeyPath,szClsModel='', nThreads=4): def _OcrInit(self,szDetModel, szRecModel, szKeyPath,szClsModel='', nThreads=4):
_OcrInit=self.dll.OcrInit _OcrInit=self.dll.OcrInit

View File

@ -1,203 +0,0 @@
STRING = 12
MESSAGE_SIZE = 500
PIPE_BUFFER_SIZE = 50000
SHIFT_JIS = 932
MAX_MODULE_SIZE = 120
PATTERN_SIZE = 30
HOOK_NAME_SIZE = 60
FIXED_SPLIT_VALUE = 0x10001
import ctypes
from ctypes import Structure,c_int,c_char,c_uint64,c_uint,sizeof,c_wchar,c_short,c_uint32,c_bool,c_ubyte
class HostNotificationType(c_int):
pass
HOST_NOTIFICATION_TEXT=0
HOST_NOTIFICATION_NEWHOOK=1
HOST_NOTIFICATION_FOUND_HOOK=2
HOST_NOTIFICATION_RMVHOOK=3
HOST_NOTIFICATION_INSERTHOOK=4
class HostCommandType(c_uint):
pass
HOST_COMMAND_NEW_HOOK=0
HOST_COMMAND_REMOVE_HOOK=1
HOST_COMMAND_FIND_HOOK=2
HOST_COMMAND_MODIFY_HOOK=3
HOST_COMMAND_HIJACK_PROCESS=4
HOST_COMMAND_DETACH=5
HOST_COMMAND_NEW_HOOK_NAIVE=6
class ThreadParam(Structure):
_fields_=[
('processId',c_uint),
('addr',c_uint64),
('ctx',c_uint64),
('ctx2',c_uint64)
]
def __hash__(self):
return hash((self.processId, self.addr,self.ctx,self.ctx2))
def __eq__(self, __value ):
return self.__hash__()==__value.__hash__()
class HookParam(Structure):
_fields_=[
('address',c_uint64),
('offset',c_int),
('index',c_int),
('split',c_int),
('split_index',c_int),
('null_length',c_int),
('module',c_wchar*MAX_MODULE_SIZE),
('function',c_char*MAX_MODULE_SIZE),
('type',c_uint),
('codepage', c_uint),
('length_offset',c_short),
('padding',c_uint64), #uintptr_t
('user_value',c_uint),
('text_fun',c_uint64),
('filter_fun',c_uint64),
('hook_fun',c_uint64),
('length_fun',c_uint64), #函数指针
('_1',c_uint64),
('_2',c_uint64),
('_3',c_uint64),
('_4',c_uint64),
('name',c_char*HOOK_NAME_SIZE)
]
class TextHook(Structure):
_fields_=[
('hp',HookParam),
('address',c_uint64), #union{uint64 && void*}
('useCount',c_uint),
('readerThread',c_uint64), #HANLDE ->void*
('readerEvent',c_uint64),
('err',c_bool),
('trampoline',c_ubyte*140),
('local_buffer',c_uint64)
]
MAX_HOOK=2500
class SearchParam(Structure):
_fields_=[
('pattern',c_char*30),
('address_method',c_int),
('search_method',c_int),
('length',c_int),
('offset',c_int),
('searchTime',c_int),
('maxRecords',c_int),
('codepage',c_int),
('padding',c_uint64),
('minAddress',c_uint64),
('maxAddress',c_uint64),
('boundaryModule',c_wchar*120),
('exportModule',c_wchar*120),
('text',c_wchar*30)
]
class DetachCmd(Structure):
_fields_=[
('command',HostCommandType),
]
def __init__(self) -> None:
self.command=HOST_COMMAND_DETACH
class RemoveHookCmd(Structure):
_fields_=[
('command',HostCommandType),
('address',c_uint64)
]
def __init__(self, address) -> None:
self.command=HOST_COMMAND_REMOVE_HOOK
self.address=address
class InsertHookCmd(Structure):
_fields_=[
('command',HostCommandType),
('hp',HookParam)
]
def __init__(self, hp) -> None:
self.command=HOST_COMMAND_NEW_HOOK
self.hp=hp
class InsertHookCodeNaive(Structure):
_fields_=[
('command',HostCommandType),
('hcode',c_wchar*500)
]
def __init__(self, hp) -> None:
self.command=HOST_COMMAND_NEW_HOOK_NAIVE
self.hcode=hp
class FindHookCmd(Structure):
_fields_=[
('command',HostCommandType),
('sp',SearchParam)
]
def __init__(self, sp) -> None:
self.command=HOST_COMMAND_FIND_HOOK
self.sp=sp
class RemoveHookCmd(Structure):
_fields_=[
('command',HostCommandType),
('address',c_uint64)
]
def __init__(self, address) -> None:
self.command=HOST_COMMAND_REMOVE_HOOK
self.address=address
class hookfoundtext(Structure):
_fields_=[('text',c_wchar*MESSAGE_SIZE)]
class HookFoundNotif(Structure):
_fields_=[
('command',HostNotificationType),
('hp',HookParam),
('hcode',c_wchar*500),
('text',hookfoundtext)
]
class ConsoleOutputNotif(Structure):
_fields_=[
('command',HostNotificationType),
('message',c_char*MESSAGE_SIZE)
]
class HookRemovedNotif(Structure):
_fields_=[
('command',HostNotificationType),
('address',c_uint64)
]
class HookInsertingNotif(Structure):
_fields_=[
('command',HostNotificationType),
('addr',c_uint64),
]
SHAREDMEMDPREFIX='LUNA_VNR_SECTION_'
HOOKCODEGET='LUNA_HOOKCODE_'
HOOK_PIPE_NAME="\\\\.\\pipe\\LUNA_HOOK"
HOST_PIPE_NAME="\\\\.\\pipe\\LUNA_HOST"
PIPE_AVAILABLE_EVENT = "LUNA_PIPE_AVAILABLE"
class Hookcodeshared(Structure):
_fields_=[('code',c_wchar*500)]
class EmbedSharedMem(ctypes.Structure):
_fields_=[
('using',ctypes.c_uint64*10),
('addr',ctypes.c_uint64*10),
('ctx1',ctypes.c_uint64*10),
('ctx2',ctypes.c_uint64*10),
('waittime',ctypes.c_uint32),
('spaceadjustpolicy',ctypes.c_uint32),
('keeprawtext',ctypes.c_uint32),
('hash',ctypes.c_uint64),
('text',ctypes.c_wchar*1000),
('fontCharSetEnabled',ctypes.c_bool),
('fontCharSet',ctypes.c_uint8),
('fontFamily',ctypes.c_wchar*100),
]
EMBED_SHARED_MEM="EMBED_SHARED_MEM"
LUNA_NOTIFY="LUNA_NOTIFY.%s.%s"
ITH_HOOKMAN_MUTEX_="LUNA_VNR_HOOKMAN_"

View File

@ -1,265 +0,0 @@
import textsource.hook.define as define
import windows
from traceback import print_exc
#import define
import re,copy
USING_STRING = 0x1 # type(data) is char * or wchar_t * and has length
USING_UNICODE = 0x2 # type(data) is wchar_t or wchar_t*
BIG_ENDIAN = 0x4 # type(data) is char
DATA_INDIRECT = 0x8
USING_SPLIT = 0x10 # use ctx2 or not
SPLIT_INDIRECT = 0x20
MODULE_OFFSET = 0x40 # address is relative to module
FUNCTION_OFFSET = 0x80 # address is relative to function
USING_UTF8 = 0x100
NO_CONTEXT = 0x200
HOOK_EMPTY = 0x400
FIXING_SPLIT = 0x800
DIRECT_READ = 0x1000 # /R read code instead of classic / H hook code
FULL_STRING = 0x2000
HEX_DUMP = 0x4000
HOOK_ENGINE = 0x8000
HOOK_ADDITIONAL = 0x10000
KNOWN_UNSTABLE = 0x20000
def ConsumeHexInt(HCode):
match = re.match(r'^([+-]?[0-9a-fA-F]+)', HCode)
if match:
value = int(match.group(1), 16)
HCode = HCode[match.end():]
return HCode,value
else:
return HCode,0
def Hex(st):
return hex(st).replace('0x','').upper()
def ParseRCode(RCode) :
hp=define.HookParam()
hp.type |= DIRECT_READ
if RCode[0]=='S':
pass
elif RCode[0] == 'Q':
hp.type |= USING_UNICODE
elif RCode[0] == 'V':
hp.type |= USING_UTF8
elif RCode[0] == 'M':
hp.type |= USING_UNICODE | HEX_DUMP
else:
return None
RCode = RCode[1:]
# [null_length<]
match = re.match(r"^([0-9]+)<", RCode)
if match:
hp.null_length = int(match.group(1))
RCode = RCode[len(match.group(0)):]
# [codepage#]
match = re.match(r"^([0-9]+)#", RCode)
if match:
hp.codepage = int(match.group(1))
RCode = RCode[len(match.group(0)):]
# @addr
match = re.match(r"@([0-9a-fA-F]+)", RCode)
if not match:
return None
hp.address = int(match.group(1), 16)
return hp
def ParseHCode(HCode):
hp=define.HookParam()
if HCode[0] == 'A':
hp.type |= BIG_ENDIAN
hp.length_offset = 1
elif HCode[0] == 'B':
hp.length_offset = 1
elif HCode[0] == 'W':
hp.type |= USING_UNICODE
hp.length_offset = 1
elif HCode[0] == 'H':
hp.type |= USING_UNICODE | HEX_DUMP
hp.length_offset = 1
elif HCode[0] == 'S':
hp.type |= USING_STRING
elif HCode[0] == 'Q':
hp.type |= USING_STRING | USING_UNICODE
elif HCode[0] == 'V':
hp.type |= USING_STRING | USING_UTF8
elif HCode[0] == 'M':
hp.type |= USING_STRING | USING_UNICODE | HEX_DUMP
else:
return None
HCode = HCode[1:]
if hp.type & USING_STRING:
if HCode[0] == 'F':
hp.type |= FULL_STRING
HCode = HCode[1:]
# [null_length<]
match = re.match(r'^([0-9]+)<', HCode)
if match:
hp.null_length = int(match.group(1))
HCode = HCode[match.end():]
# [N]
if HCode[0] == 'N':
hp.type |= NO_CONTEXT
HCode = HCode[1:]
# [codepage#]
match = re.match(r'^([0-9]+)#', HCode)
if match:
hp.codepage = int(match.group(1))
HCode = HCode[match.end():]
# [padding+]
match = re.match(r'^([0-9a-fA-F]+)\+', HCode)
if match:
hp.padding = int(match.group(1), 16)
HCode = HCode[match.end():]
HCode,hp.offset=ConsumeHexInt(HCode)
# [*deref_offset1]
if HCode[0] == '*':
hp.type |= DATA_INDIRECT
HCode = HCode[1:]
HCode,hp.index=ConsumeHexInt(HCode)
# [:split_offset[*deref_offset2]]
if HCode[0] == ':':
hp.type |= USING_SPLIT
HCode = HCode[1:]
HCode,hp.split=ConsumeHexInt(HCode)
if HCode[0] == '*':
hp.type |= SPLIT_INDIRECT
HCode = HCode[1:]
HCode,hp.split_index=ConsumeHexInt(HCode)
# @addr[:module[:func]]
match = re.match(r'^@([0-9a-fA-F]+)(:.+?)?(:.+)?$', HCode)
if match is None:
return None
hp.address = int(match.group(1), 16)
if match.group(2):
hp.type |= MODULE_OFFSET
hp.module = match.group(2)[1:]
if match.group(3):
hp.type |= FUNCTION_OFFSET
hp.function =bytes(match.group(3)[1:],encoding='ascii')
# ITH has registers offset by 4 vs AGTH: need this to correct
if hp.offset < 0:
hp.offset -= 4
if hp.split < 0:
hp.split -= 4
return hp
def Parse(code):
code=code.strip().replace('\r','').replace('\n','').replace('\t','')
if(code[0]=='/'):code=code[1:]
if('/' in code):code=code.split('/')[0]
if(code[0]=='R'):
hp=ParseRCode(code[1:])
elif(code[0]=='H'):
hp=ParseHCode(code[1:])
else:
hp=None
return hp
def GenerateRCode(hp):
RCode = 'R'
if hp.type & USING_UNICODE:
if hp.type & HEX_DUMP:
RCode += 'M'
else:
RCode += 'Q'
if hp.null_length != 0:
RCode += str(hp.null_length) + '<'
else:
RCode += 'S'
if hp.null_length != 0:
RCode += str(hp.null_length) + '<'
if hp.codepage != 0:
RCode += str(hp.codepage) + '#'
RCode += '@' + Hex(hp.address)
return RCode
def GenerateHCode(hp,processId):
HCode = "H"
if hp.type & USING_UNICODE:
if hp.type & HEX_DUMP:
if hp.type & USING_STRING:
HCode += "M"
else:
HCode += "H"
else:
if hp.type & USING_STRING:
HCode += "Q"
else:
HCode += "W"
else:
if hp.type & USING_STRING:
HCode += "S"
elif hp.type & BIG_ENDIAN:
HCode += "A"
else:
HCode += "B"
if hp.type & FULL_STRING:
HCode += "F"
if hp.null_length != 0:
HCode += str(hp.null_length) + "<"
if hp.type & NO_CONTEXT:
HCode += "N"
if hp.text_fun or hp.filter_fun or hp.hook_fun or hp.length_fun:
HCode += "X" # no AGTH equivalent
if hp.codepage != 0 and not (hp.type & USING_UNICODE):
HCode += str(hp.codepage) + "#"
if hp.padding:
HCode += Hex(hp.padding) + "+"
if hp.offset < 0:
hp.offset += 4
if hp.split < 0:
hp.split += 4
HCode += Hex(hp.offset)
if hp.type & DATA_INDIRECT:
HCode += "*" + Hex(hp.index)
if hp.type & USING_SPLIT:
HCode += ":" + Hex(hp.split)
if hp.type & SPLIT_INDIRECT:
HCode += "*" + Hex(hp.split_index)
# Attempt to make the address relative
try:
if processId and not (hp.type & MODULE_OFFSET):
process =windows.AutoHandle(windows.OpenProcess(windows.PROCESS_VM_READ | windows.PROCESS_QUERY_INFORMATION, False, processId))
if process:
info=windows.VirtualQueryEx(process,hp.address)
if info.AllocationBase:
module_name =windows.GetModuleFileNameEx(process, info.AllocationBase)
if module_name:
hp.address -= info.AllocationBase
hp.type |= MODULE_OFFSET
hp.module = module_name[module_name.rfind('\\')+1:][:120]
except:
pass
#print_exc()
HCode += "@" + Hex(hp.address)
if hp.type & MODULE_OFFSET:
HCode += ":" + hp.module
if hp.type & FUNCTION_OFFSET:
HCode += ":" + hp.function.decode('ascii')
return HCode
def Generate(_hp,process_id):
hp=copy.copy(_hp)
if hp.type&DIRECT_READ :
code=GenerateRCode(hp)
else:
code=GenerateHCode(hp,process_id)
return code
if __name__=='__main__':
# print(Parse("/HQN936#1+-c*C:C*1C@4AA:gdi.dll:GetTextOutA",hp))
# print(Parse("/HQN936#-c*C:C*1C@4AA:gdi.dll:GetTextOutA /KF",hp))
# print(Parse("HB4@0" ,hp)),
# print(Parse("/RS65001#@44",hp)),
# print(Parse("HQ@4",hp,))
print(Parse('/HS8:-14@76D85270'))
# print(Parse("/RW@44",hp)),
# print(Parse("/HWG@33",hp))

View File

@ -1,303 +0,0 @@
import threading
import textsource.hook.define as define
import ctypes,time
from ctypes import Structure,c_int,c_char,sizeof,cast,POINTER
from myutils.wrapper import threader
import sys
import os ,subprocess
from myutils.config import globalconfig
import windows
from myutils.hwnd import testprivilege
import ctypes
import textsource.hook.hookcode as hookcode
class ProcessRecord():
def __init__(self,pipe,processId) -> None:
self.pipe=pipe
self.processId=processId
buff=define.MAX_HOOK*define.TextHook
HOOK_SECTION_SIZE=sizeof(buff)
self.OnHookFound=0
fmap1=windows.OpenFileMapping(windows.FILE_MAP_READ,False,define.SHAREDMEMDPREFIX+str(processId))
address1=windows.MapViewOfFile(fmap1, windows.FILE_MAP_READ, HOOK_SECTION_SIZE)
fmap2=windows.OpenFileMapping(windows.FILE_MAP_READ,False,define.HOOKCODEGET+str(processId))
address2=windows.MapViewOfFile(fmap2, windows.FILE_MAP_READ, sizeof(define.MAX_HOOK*define.Hookcodeshared))
self.sharedtexthook=cast(address1,POINTER(buff))
self.sharedhookcode=cast(address2,POINTER(define.MAX_HOOK*define.Hookcodeshared))
def GetHook(self,addr):
for i,_hook in enumerate(self.sharedtexthook.contents):
if(_hook.address==addr):
code=self.sharedhookcode.contents[i].code
return _hook,code
return None,None
def Send(self,struct):
windows.WriteFile(self.pipe,bytes(struct))
#calls
def Detach(self):
self.Send(define.DetachCmd())
def RemoveHook(self,address):
self.Send((define.RemoveHookCmd(address)))
def InsertHookCode(self,string):
if len(string) and string[0]=='E':
self.Send(define.InsertHookCodeNaive(string))
else:
hp=hookcode.Parse(string)
print(hp)
if hp:
self.Send(define.InsertHookCmd(hp))
return True
else:
return False
def FindHooks(self,sp,OnHookFound):
self.OnHookFound=OnHookFound
self.Send(define.FindHookCmd(sp))
self.OnHookFound=OnHookFound
def RemoveHook(self,addr):
self.Send(define.RemoveHookCmd(addr));
class TextThread():
def __init__(self,rpc,tp,_,host) -> None:
(texthook,hcode)=_
hp=texthook.hp
self.tp=tp
self.rpc=rpc
self.hp=hp
self.hpcode=hcode#hookcode.Generate(hp,tp.processId)
self.host=host
self.buffer=''
self.lasttime=0
self.lock=threading.Lock()
self.leadbyte=0
self.saverepeat=''
def Push(self,buff):
self.lock.acquire()
buffer=self.parsebuff(buff)
if self.rpc.setting.timeout==0 and self.hp.type&hookcode.FULL_STRING:
self.rpc.Output(self,buffer)
elif not( globalconfig['direct_filterrepeat']and (len(buffer)>=3) and (buffer in self.saverepeat)):
self.buffer+=buffer
self.lasttime=time.time()
if len(self.buffer):
self.saverepeat=self.buffer
if len(self.buffer)>=self.host.setting.flushbuffersize:
_=self.buffer
self.buffer=''
self.rpc.Output(self,_)
self.lock.release()
def parsebuff(self,buff):
hp=self.hp
if hp.codepage==0:
cp=self.host.setting.defaultcodepag
else:
cp=hp.codepage
if len(buff)==1:
if self.leadbyte:
buff=self.leadbyte+buff
self.leadbyte=0
else:
if(windows.IsDBCSLeadByteEx(cp,buff[0])):
self.leadbyte=buff
return ''
if (hp.type &hookcode.HEX_DUMP) :
_ret=buff.hex()
elif hp.type& hookcode.USING_UNICODE:
try:
_ret=buff.decode('utf-16',errors='ignore')
except:
return ''
else:
if hp.codepage==0:
cp=self.host.setting.defaultcodepag
else:
cp=hp.codepage
_ret=windows.MultiByteToWideChar(buff,len(buff),cp)
if _ret is None:
_ret=''
if hp.type&hookcode.FULL_STRING:
_ret+='\n'
return _ret
class RPCSettings:
def __init__(self) -> None:
self.timeout=100
self.defaultcodepag=932
self.flushbuffersize=3000
class RPC():
def callbacks(self,OnConnect,OnDisconnect,OnCreate,OnDestroy,Output,Console,EmbedCall,HookInsert):
self.OnDisconnect=threader(OnDisconnect)
self.OnConnect=threader(OnConnect)
self.OnCreate=(OnCreate) #有并发问题会插入Embed的text两次
self.OnDestroy=threader(OnDestroy)
self.Output=threader(Output)
self.Console=threader(Console)
self.EmbedCall=threader(EmbedCall)
self.HookInsert=threader(HookInsert)
def toint(self,byte4):
return c_int.from_buffer_copy(byte4).value
def end(self):
for _ in self.hookPipes:
windows.CancelIo(_)
def __init__(self) -> None:
self.ProcessRecord={}
self.textthreadslock=threading.Lock()
self.textthreads={}
self.hookPipes=[]
self.setting=RPCSettings()
threading.Thread(target=self.outputthread).start()
def outputthread(self):
while True:
time.sleep(0.001)
timenow=time.time()
self.textthreadslock.acquire()
for _,textthread in self.textthreads.items():
textthread.lock.acquire()
if len(textthread.buffer)>0 and (timenow-textthread.lasttime>self.setting.timeout/1000):
buff=textthread.buffer
textthread.buffer=''
self.Output(textthread,buff)
textthread.lasttime=timenow
textthread.lock.release()
self.textthreadslock.release()
def start(self,pid):
hookPipe = windows.CreateNamedPipe(define.HOOK_PIPE_NAME+str(pid),
windows.PIPE_ACCESS_INBOUND,
windows.PIPE_TYPE_MESSAGE | windows.PIPE_READMODE_MESSAGE | windows.PIPE_WAIT,
windows.PIPE_UNLIMITED_INSTANCES,
0,
0,
0)
hostPipe = windows.CreateNamedPipe(define.HOST_PIPE_NAME+str(pid),
windows.PIPE_ACCESS_OUTBOUND,
windows.PIPE_TYPE_MESSAGE | windows.PIPE_READMODE_MESSAGE | windows.PIPE_WAIT,
windows.PIPE_UNLIMITED_INSTANCES,
0,
0,
0 )
pipeAvailableEvent = windows.CreateEvent(False, False, define.PIPE_AVAILABLE_EVENT+str(pid))
windows.SetEvent(pipeAvailableEvent)
self.hookPipes.append(hookPipe)
def _():
windows.ConnectNamedPipe(hookPipe, None)
windows.CloseHandle(pipeAvailableEvent)
processId = self.toint(windows.ReadFile(hookPipe, 4,None) )
self.ProcessRecord[processId]=ProcessRecord(hostPipe,processId)
self.OnConnect(processId)
while True:
data=windows.ReadFile(hookPipe,50000,None)
if len(data)==0 :break
if len(data)==50000:continue
self.OnMessage(data,processId)
self.ProcessRecord.pop(processId)
windows.CloseHandle(hookPipe)
windows.CloseHandle(hostPipe)
self.removethreads(processId)
self.OnDisconnect((processId))
threading.Thread(target=_,daemon=True).start()
def removethreads(self,pid,addr=None):
self.textthreadslock.acquire()
toremove=[]
for textthread in self.textthreads:
if textthread.processId==pid:
if addr:
if textthread.addr==addr:
toremove.append(textthread)
else:
toremove.append(textthread)
for _ in toremove:
self.textthreads.pop(_)
self.OnDestroy(_)
self.textthreadslock.release()
def OnMessage(self,data,processId):
cmd=self.toint(data[:4])
if(cmd==define. HOST_NOTIFICATION_TEXT):
try:
message=define.ConsoleOutputNotif.from_buffer_copy(data).message.decode('utf8')
except:
message="ErrorDecodeMessage"
self.Console(message)
elif(cmd==define.HOST_NOTIFICATION_FOUND_HOOK):
_HookFoundNotif=define.HookFoundNotif
_HookFoundNotif=_HookFoundNotif.from_buffer_copy(data)
text=_HookFoundNotif.text.text
#print(_HookFoundNotif.hcode,hookcode.Generate(_HookFoundNotif.hp,processId))
hp=hookcode.Parse(_HookFoundNotif.hcode)
if len(text)>12:
self.ProcessRecord[processId].OnHookFound(hookcode.Generate(hp,processId),text)
hp.type&=~hookcode.USING_UNICODE
codepages=[hp.codepage]
if hp.codepage!=65001:
codepages+=[65001]
for codepage in codepages:
try:
hp.codepage=codepage
text=windows.MultiByteToWideChar(_HookFoundNotif.text.text,sizeof(define.hookfoundtext),hp.codepage)
if text is not None and len(text)>12:
self.ProcessRecord[processId].OnHookFound(hookcode.Generate(hp,processId),text)
except:pass
elif(cmd==define.HOST_NOTIFICATION_RMVHOOK):
self.removethreads(processId,define.HookRemovedNotif.from_buffer_copy(data).address)
elif(cmd==define.HOST_NOTIFICATION_INSERTHOOK):
addr=define.HookInsertingNotif.from_buffer_copy(data).addr
_,hcode=self.ProcessRecord[processId].GetHook(addr)
self.HookInsert(addr,hcode)
else:
tp=define.ThreadParam.from_buffer_copy(data)
if tp not in self.textthreads:
self.textthreadslock.acquire()
self.textthreads[tp]=TextThread(self,tp,self.ProcessRecord[tp.processId].GetHook(tp.addr),self)
self.OnCreate(self.textthreads[tp])
self.textthreadslock.release()
if self.textthreads[tp].hpcode[0]=='E':
#self.Output(self.textthreads[tp],self.textthreads[tp].parsebuff(data[sizeof(tp):]))
self.EmbedCall(self.textthreads[tp].parsebuff(data[sizeof(tp):]),self.textthreads[tp])
self.textthreads[tp].Push(data[sizeof(tp):])
#
def Attach(self,pids,arch):
injecter=os.path.abspath('./files/plugins/shareddllproxy{}.exe'.format(arch))
dll=os.path.abspath('./files/plugins/LunaHook/LunaHook{}.dll'.format(arch))
print(injecter,os.path.exists(injecter))
print(dll,os.path.exists(dll))
#subprocess.Popen('"{}" dllinject {} "{}"'.format(injecter,pid,dll))
pid=' '.join([str(_) for _ in pids])
if any(map(testprivilege,pids))==False:
windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE)
else:
ret=subprocess.run('"{}" dllinject {} "{}"'.format(injecter,pid,dll)).returncode
if(ret==0):
windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE)
@threader
def InsertHookCode(self,pid,hookcode):
if pid in self.ProcessRecord:
self.ProcessRecord[pid].InsertHookCode(hookcode)
@threader
def FindHooks(self,pid,sp,onfound):
if pid in self.ProcessRecord:
self.ProcessRecord[pid].FindHooks(sp,onfound)
@threader
def Detach(self,pid):
if pid in self.ProcessRecord:
self.ProcessRecord[pid].Detach()
@threader
def RemoveHook(self,pid,addr):
if pid in self.ProcessRecord:
self.ProcessRecord[pid].RemoveHook(addr)

View File

@ -4,17 +4,67 @@ import re ,os
import time ,gobject import time ,gobject
from collections import OrderedDict from collections import OrderedDict
import ctypes,functools import ctypes,functools
import windows import windows,subprocess
import textsource.hook.define as define
from myutils.config import globalconfig ,savehook_new_data ,_TR,static_data from myutils.config import globalconfig ,savehook_new_data ,_TR,static_data
from textsource.textsourcebase import basetext from textsource.textsourcebase import basetext
from myutils.utils import checkchaos from myutils.utils import checkchaos
from textsource.hook.host import RPC from myutils.hwnd import testprivilege
from myutils.wrapper import threader
from ctypes import CDLL,c_bool,POINTER,Structure,c_int,pointer,c_wchar_p,c_uint64,sizeof,c_void_p,cast,c_wchar,c_uint32,c_uint8,c_uint,c_char,c_short
from ctypes.wintypes import DWORD,LPCWSTR,HANDLE
from gui.usefulwidget import getQMessageBox
MAX_MODULE_SIZE = 120
HOOK_NAME_SIZE = 60
HOOKCODE_LEN=500
class ThreadParam(Structure):
_fields_=[
('processId',c_uint),
('addr',c_uint64),
('ctx',c_uint64),
('ctx2',c_uint64)
]
def __hash__(self):
return hash((self.processId, self.addr,self.ctx,self.ctx2))
def __eq__(self, __value ):
return self.__hash__()==__value.__hash__()
class SearchParam(Structure):
_fields_=[
('pattern',c_char*30),
('address_method',c_int),
('search_method',c_int),
('length',c_int),
('offset',c_int),
('searchTime',c_int),
('maxRecords',c_int),
('codepage',c_int),
('padding',c_uint64),
('minAddress',c_uint64),
('maxAddress',c_uint64),
('boundaryModule',c_wchar*120),
('exportModule',c_wchar*120),
('text',c_wchar*30),
('_1',c_uint64)
]
class Message(Structure):
_fields_=[
('read',c_bool),
('type',c_int),
('pid',DWORD),
('hn',c_char*HOOK_NAME_SIZE),
('hc',c_wchar*HOOKCODE_LEN),
('tp',ThreadParam),
('stringptr',c_void_p),
('addr',c_uint64)
]
class simplehooks(Structure):
_fields_=[
('hookcode',c_wchar*500),
('text',c_void_p)
]
class texthook(basetext ): class texthook(basetext ):
def __init__(self,pids,hwnd,pname ,autostarthookcode=None,needinserthookcode=None) : def __init__(self,pids,hwnd,pname ,autostarthookcode=None,needinserthookcode=None) :
print(pids,hwnd,pname ,autostarthookcode,needinserthookcode)
self.RPC=RPC()
if autostarthookcode is None: if autostarthookcode is None:
autostarthookcode=[] autostarthookcode=[]
if needinserthookcode is None: if needinserthookcode is None:
@ -43,84 +93,143 @@ class texthook(basetext ):
self.isremoveuseless=savehook_new_data[self.pname]["removeuseless"] and len(self.autostarthookcode) self.isremoveuseless=savehook_new_data[self.pname]["removeuseless"] and len(self.autostarthookcode)
self.needinserthookcode=needinserthookcode self.needinserthookcode=needinserthookcode
self.removedaddress=[] self.removedaddress=[]
self.HookCode=None
self.sharedcell=None
self.RPC.callbacks(
lambda pid:time.sleep(savehook_new_data[self.pname]['inserthooktimeout']/1000) or [self.RPC.InsertHookCode(pid,hookcode) for hookcode in needinserthookcode]+[self.createembedsharedmem(pid),self.showgamename()],
lambda pid: print(pid,"disconenct"),
self.onnewhook,
self.onremovehook,
self.handle_output,
gobject.baseobject.hookselectdialog.sysmessagesignal.emit,
self.getembedtext,
self.newhookinsert
)
self.setsettings()
gobject.baseobject.hookselectdialog.changeprocessclearsignal.emit() gobject.baseobject.hookselectdialog.changeprocessclearsignal.emit()
if len(autostarthookcode)==0 and len(savehook_new_data[self.pname]['embedablehook'])==0: if len(autostarthookcode)==0 and len(savehook_new_data[self.pname]['embedablehook'])==0:
gobject.baseobject.hookselectdialog.realshowhide.emit(True) gobject.baseobject.hookselectdialog.realshowhide.emit(True)
threading.Thread(target=self.delaycollectallselectedoutput).start() threading.Thread(target=self.delaycollectallselectedoutput).start()
_pids=[]
for pid in self.pids:
if self.testalready(pid)==False:
self.RPC.start(pid)
_pids.append(pid)
if len(_pids):
self.RPC.Attach(_pids,'64' if self.is64bit else '32')
super(texthook,self).__init__(*self.checkmd5prefix(pname)) super(texthook,self).__init__(*self.checkmd5prefix(pname))
def testalready(self,pid): self.declare()
_mutext=windows.AutoHandle(windows.CreateMutex(False,define.ITH_HOOKMAN_MUTEX_+str(pid))) self.start()
err=windows.GetLastError() def declare(self):
exists= err==windows.ERROR_ALREADY_EXISTS LunaHost=CDLL(gobject.GetDllpath(('LunaHost32.dll','LunaHost64.dll')))
return exists self.Luna_Settings=LunaHost.Luna_Settings
self.Luna_Settings.argtypes=c_int,c_bool,c_int,c_int
self.Luna_Start=LunaHost.Luna_Start
self.Luna_Start.argtypes=POINTER(HANDLE),
self.Luna_Inject=LunaHost.Luna_Inject
self.Luna_Inject.argtypes=DWORD,LPCWSTR
self.Luna_CreatePipeAndCheck=LunaHost.Luna_CreatePipeAndCheck
self.Luna_CreatePipeAndCheck.argtypes=DWORD,
self.Luna_CreatePipeAndCheck.restype=c_bool
self.Luna_InsertHookCode=LunaHost.Luna_InsertHookCode
self.Luna_InsertHookCode.argtypes=DWORD,LPCWSTR
self.Luna_InsertHookCode.restype=c_bool
self.Luna_RemoveHook=LunaHost.Luna_RemoveHook
self.Luna_RemoveHook.argtypes=DWORD,c_uint64
self.Luna_Detach=LunaHost.Luna_Detach
self.Luna_Detach.argtypes=DWORD,
self.Luna_cfree=LunaHost.Luna_cfree
self.Luna_cfree.argtypes=c_void_p,
self.Luna_FindHooks=LunaHost.Luna_FindHooks
self.Luna_FindHooks.argtypes=DWORD,SearchParam,POINTER(HANDLE),POINTER(POINTER(c_int))
self.Luna_FindHooks_waiting=LunaHost.Luna_FindHooks_waiting
self.Luna_FindHooks_waiting.argtypes=POINTER(c_int),
self.Luna_EmbedSettings=LunaHost.Luna_EmbedSettings
self.Luna_EmbedSettings.argtypes=DWORD,c_uint32,c_uint8,c_bool,c_wchar_p,c_uint32,c_uint32
self.Luna_checkisusingembed=LunaHost.Luna_checkisusingembed
self.Luna_checkisusingembed.argtypes=DWORD,c_uint64,c_uint64,c_uint64
self.Luna_checkisusingembed.restype=c_bool
self.Luna_useembed=LunaHost.Luna_useembed
self.Luna_useembed.argtypes=DWORD,c_uint64,c_uint64,c_uint64,c_bool
self.Luna_embedcallback=LunaHost.Luna_embedcallback
self.Luna_embedcallback.argtypes=DWORD,LPCWSTR,LPCWSTR
def start(self):
self.hRead=HANDLE()
self.Luna_Start(pointer(self.hRead) )
self.setsettings()
injectpids=[]
for pid in self.pids:
if globalconfig['use_yapi']:
self.Luna_Inject(pid,os.path.abspath('./files/plugins/LunaHook'))
else:
if(self.Luna_CreatePipeAndCheck(pid)):
injectpids.append(pid)
if len(injectpids):
arch=['32','64'][self.is64bit]
injecter=os.path.abspath('./files/plugins/shareddllproxy{}.exe'.format(arch))
dll=os.path.abspath('./files/plugins/LunaHook/LunaHook{}.dll'.format(arch))
print(injecter,os.path.exists(injecter))
print(dll,os.path.exists(dll))
#subprocess.Popen('"{}" dllinject {} "{}"'.format(injecter,pid,dll))
pid=' '.join([str(_) for _ in injectpids])
if any(map(testprivilege,injectpids))==False:
windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE)
else:
ret=subprocess.run('"{}" dllinject {} "{}"'.format(injecter,pid,dll)).returncode
if(ret==0):
windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE)
threading.Thread(target=self.solveeventthread).start()
@threader
def onprocconnect(self,pid):
time.sleep(savehook_new_data[self.pname]['inserthooktimeout']/1000)
for hookcode in self.needinserthookcode:
self.Luna_InsertHookCode(pid,hookcode)
self.showgamename()
self.flashembedsettings(pid)
def solveeventthread(self):
while self.ending==False:
message=windows.ReadFile(self.hRead,sizeof(Message),None)
if len(message)!=sizeof(Message):break
message=Message.from_buffer_copy(message)
_type=message.type
if _type in [0,1]:
pid=(message.pid)
if _type==0:
self.onprocconnect(pid)
elif _type==1:
gobject.baseobject.hookselectdialog.sysmessagesignal.emit('{} disconenct'.format(pid))
elif _type in [2,3]:
if _type==2:
self.onnewhook(message.hc,message.hn,message.tp)
elif _type==3:
self.onremovehook(message.tp)
elif _type==4:
self.handle_output(message.hc,message.hn,message.tp,cast(message.stringptr,c_wchar_p).value)
elif _type==5:
gobject.baseobject.hookselectdialog.sysmessagesignal.emit(cast(message.stringptr,c_wchar_p).value)
elif _type==6:
self.newhookinsert(message.addr,cast(message.stringptr,c_wchar_p).value)
elif _type==7:
self.getembedtext(cast(message.stringptr,c_wchar_p).value,message.tp)
if message.stringptr:
self.Luna_cfree(message.stringptr)
def newhookinsert(self,addr,hcode): def newhookinsert(self,addr,hcode):
for _hc,_addr,_ctx1,_ctx2 in savehook_new_data[self.pname]['embedablehook']: for _hc,_addr,_ctx1,_ctx2 in savehook_new_data[self.pname]['embedablehook']:
if hcode==_hc: if hcode==_hc:
self.useembed(addr,_ctx1,_ctx2,True) self.useembed(addr,_ctx1,_ctx2,True)
def getembedtext(self,text,tt): def getembedtext(self,text,tp):
if globalconfig['autorun']==False: if globalconfig['autorun']==False:
self.embedcallback(text,0,text) self.embedcallback(text,0,text)
return return
if self.checkisusingembed(tt.tp.addr,tt.tp.ctx,tt.tp.ctx2): if self.checkisusingembed(tp.addr,tp.ctx,tp.ctx2):
self.newline.put((text,False, functools.partial(self.embedcallback,text),True)) self.newline.put((text,False, functools.partial(self.embedcallback,text),True))
def embedcallback(self,text,_unused,trans): def embedcallback(self,text,_unused,trans):
self.sharedcell.contents.text=trans
self.notify(self.EMBEDPID,text) for pid in self.pids:
def createembedsharedmem(self,pid): self.Luna_embedcallback(pid,text,trans)
self.EMBEDPID=pid def flashembedsettings(self,pid=None):
fmap1=windows.OpenFileMapping(windows.FILE_MAP_READ|0x2,False,'EMBED_SHARED_MEM'+str(pid)) if pid:
address1=windows.MapViewOfFile(fmap1, windows.FILE_MAP_READ|0x2, 4096) pids=[pid]
else:
self.sharedcell=ctypes.cast(address1,ctypes.POINTER(define.EmbedSharedMem)) pids=self.pids
self.flashembedsettings() for pid in pids:
def flashembedsettings(self): self.Luna_EmbedSettings(pid,
if self.sharedcell is None:return int(1000* globalconfig['embedded']['timeout_translate']),
self.sharedcell.contents.waittime=int(1000* globalconfig['embedded']['timeout_translate']) 2, #static_data["charsetmap"][globalconfig['embedded']['changecharset_charset']]
self.sharedcell.contents.fontCharSet=2#static_data["charsetmap"][globalconfig['embedded']['changecharset_charset']] False,#globalconfig['embedded']['changecharset']
self.sharedcell.contents.fontCharSetEnabled=False#globalconfig['embedded']['changecharset'] globalconfig['embedded']['changefont_font'] if globalconfig['embedded']['changefont'] else '',
self.sharedcell.contents.fontFamily=globalconfig['embedded']['changefont_font'] if globalconfig['embedded']['changefont'] else '' globalconfig['embedded']['insertspace_policy'],
self.sharedcell.contents.spaceadjustpolicy=globalconfig['embedded']['insertspace_policy'] globalconfig['embedded']['keeprawtext'])
self.sharedcell.contents.keeprawtext=globalconfig['embedded']['keeprawtext']
def notify(self,pid,text):
_b=text.encode('utf-16-le')
def hs(text):
_b=text.encode('utf-16-le')
u64=ctypes.c_uint64(5381)
for i in range(len(_b)):
u64=ctypes.c_uint64((u64.value<<5)+u64.value+_b[i])
return (u64.value)
hash_=hs(text)
eventName = define.LUNA_NOTIFY % (pid, hash_)
ev = windows.AutoHandle(windows.CreateEvent( False, False, eventName) )
windows.SetEvent(ev)
def onremovehook(self,tp): def onremovehook(self,tp):
toremove=[] toremove=[]
self.lock.acquire() self.lock.acquire()
@ -131,26 +240,26 @@ class texthook(basetext ):
gobject.baseobject.hookselectdialog.removehooksignal.emit(key) gobject.baseobject.hookselectdialog.removehooksignal.emit(key)
self.hookdatacollecter.pop(key) self.hookdatacollecter.pop(key)
self.lock.release() self.lock.release()
def parsetextthread(self,textthread): def parsetextthread(self,hc,hn,tp):
key=( key=(
textthread.tp.processId, tp.processId,
textthread.tp.addr, tp.addr,
textthread.tp.ctx, tp.ctx,
textthread.tp.ctx2, tp.ctx2,
textthread.hp.name.decode('ascii'), hn.decode('ascii'),
textthread.hpcode hc
) )
return key return key
def match_compatibility(self,key,autostarthookcode): def match_compatibility(self,key,autostarthookcode):
base= (key[2]&0xffff,key[3]&0xffff,key[5])==(autostarthookcode[2]&0xffff,autostarthookcode[3]&0xffff,autostarthookcode[5]) base= (key[2]&0xffff,key[3]&0xffff,key[5])==(autostarthookcode[2]&0xffff,autostarthookcode[3]&0xffff,autostarthookcode[5])
name=((key[-1][:8]=='UserHook' and autostarthookcode[-1][:8]=='UserHook' )or(key[-1]==autostarthookcode[-1])) name=((key[-1][:8]=='UserHook' and autostarthookcode[-1][:8]=='UserHook' )or(key[-1]==autostarthookcode[-1]))
return base and name return base and name
def onnewhook(self,textthread): def onnewhook(self,hc,hn,tp):
key=self.parsetextthread(textthread) key=self.parsetextthread(hc,hn,tp)
if self.isremoveuseless: if self.isremoveuseless:
if key[1] not in [_[1] for _ in self.autostarthookcode]: if key[1] not in [_[1] for _ in self.autostarthookcode]:
self.RPC.RemoveHook(key[0],key[1]) self.Luna_RemoveHook(key[0],key[1])
return False return False
self.lock.acquire() self.lock.acquire()
@ -164,13 +273,11 @@ class texthook(basetext ):
self.hookdatacollecter[key]=[] self.hookdatacollecter[key]=[]
self.hooktypecollecter[key]=0 self.hooktypecollecter[key]=0
gobject.baseobject.hookselectdialog.addnewhooksignal.emit(key ,select,[textthread]) gobject.baseobject.hookselectdialog.addnewhooksignal.emit(key ,select,[hc,hn,tp])
self.lock.release() self.lock.release()
return True return True
def setsettings(self): def setsettings(self):
self.RPC.setting.timeout=globalconfig['textthreaddelay'] self.Luna_Settings(globalconfig['textthreaddelay'],globalconfig['direct_filterrepeat'],self.codepage() ,globalconfig['flushbuffersize'])
self.RPC.setting.flushbuffersize=globalconfig['flushbuffersize']
self.RPC.setting.defaultcodepag=self.codepage()
def codepage(self): def codepage(self):
try: try:
cpi=savehook_new_data[self.pname]["codepage_index"] cpi=savehook_new_data[self.pname]["codepage_index"]
@ -180,7 +287,7 @@ class texthook(basetext ):
return cp return cp
def defaultsp(self): def defaultsp(self):
usestruct=define.SearchParam() usestruct=SearchParam()
if not self.is64bit: if not self.is64bit:
usestruct.pattern=bytes([0x55,0x8b,0xec]) usestruct.pattern=bytes([0x55,0x8b,0xec])
usestruct.length=3 usestruct.length=3
@ -200,44 +307,44 @@ class texthook(basetext ):
usestruct.codepage=self.codepage() usestruct.codepage=self.codepage()
usestruct.boundaryModule=os.path.basename(self.pname) usestruct.boundaryModule=os.path.basename(self.pname)
return usestruct return usestruct
@threader
def findhook(self,usestruct): def findhook(self,usestruct):
self.savefound={} savefound={}
self.foundnum=0 pids=self.pids.copy()
def __waitforok():
#time.sleep(usestruct.searchTime/1000)
_last=0
for i in range(100):
#print(self.foundnum)
if _last!=self.foundnum or _last==0:
_last=self.foundnum
time.sleep(1)
else:
break
print('??',_last,self.foundnum)
gobject.baseobject.hookselectdialog.getfoundhooksignal.emit(self.savefound.copy())
def _(hc,text):
# try:print(hc,text)
# except:print(hc)
if hc not in self.savefound:
self.savefound[hc]=[]
self.savefound[hc].append(text)
if self.foundnum==0:
threading.Thread(target=__waitforok).start()
self.foundnum+=1
#print(self.foundnum)
for pid in self.pids:
self.RPC.FindHooks(pid,usestruct,_)
headers={}
def inserthook(self,hookcode): waiters={}
for pid in self.pids: for pid in pids:
print(hookcode) headers[pid]=HANDLE()
self.RPC.InsertHookCode(pid,hookcode) count=POINTER(c_int)()
waiters[pid]=count
self.Luna_FindHooks(pid,usestruct,pointer(headers[pid]),pointer(count))
def ReadThread(hread):
while True:
message=windows.ReadFile(hread,sizeof(simplehooks),None)
if len(message)!=sizeof(simplehooks):break
message=simplehooks.from_buffer_copy(message)
hc=message.hookcode
text=cast(message.text,c_wchar_p).value
if hc not in savefound:
savefound[hc]=[]
savefound[hc].append(text)
self.Luna_cfree(message.text)
windows.CloseHandle(hread)
threading.Thread(target=ReadThread,args=(headers[pid],)).start()
for pid in pids:
self.Luna_FindHooks_waiting(waiters[pid])
gobject.baseobject.hookselectdialog.getfoundhooksignal.emit(savefound)
def inserthook(self,hookcode):
succ=True
for pid in self.pids:
succ=self.Luna_InsertHookCode(pid,hookcode) and succ
if succ==False:
getQMessageBox(gobject.baseobject.hookselectdialog,"Error","Invalie Hook Code Format!")
def removehook(self,pid,address): def removehook(self,pid,address):
for pid in self.pids: for pid in self.pids:
self.RPC.RemoveHook(pid,address) self.Luna_RemoveHook(pid,address)
def delaycollectallselectedoutput(self): def delaycollectallselectedoutput(self):
collector=[] collector=[]
while True: while True:
@ -249,16 +356,15 @@ class texthook(basetext ):
self.newline.put(collector) self.newline.put(collector)
self.runonce_line=collector self.runonce_line=collector
collector=[] collector=[]
def handle_output(self,textthread,output): def handle_output(self,hc,hn,tp,output):
#print(output) key=self.parsetextthread(hc,hn,tp)
key=self.parsetextthread(textthread)
if globalconfig['filter_chaos_code'] and checkchaos(output): if globalconfig['filter_chaos_code'] and checkchaos(output):
return return
if key not in self.hookdatacollecter: if key not in self.hookdatacollecter:
if self.onnewhook(textthread)==False: if self.onnewhook(hc,hn,tp)==False:
return return
self.lock.acquire() self.lock.acquire()
if self.hooktypecollecter[key]==1: if self.hooktypecollecter[key]==1:
@ -284,31 +390,13 @@ class texthook(basetext ):
self.lock.release() self.lock.release()
def checkisusingembed(self,address,ctx1,ctx2): def checkisusingembed(self,address,ctx1,ctx2):
if self.sharedcell is None:return for pid in self.pids:
for i in range(10): if self.Luna_checkisusingembed(pid,address,ctx1,ctx2):
if(self.sharedcell.contents.using[i]): return True
if (self.sharedcell.contents.addr[i],self.sharedcell.contents.ctx1[i],self.sharedcell.contents.ctx2[i])==(address,ctx1,ctx2): return False
return True
return False
def useembed(self,address,ctx1,ctx2,use): def useembed(self,address,ctx1,ctx2,use):
if self.sharedcell is None:return for pid in self.pids:
for i in range(10): self.Luna_useembed(pid,address,ctx1,ctx2,use)
if(self.sharedcell.contents.using[i]):
if (self.sharedcell.contents.addr[i],self.sharedcell.contents.ctx1[i],self.sharedcell.contents.ctx2[i])==(address,ctx1,ctx2):
if use==False:
self.sharedcell.contents.addr[i]=0
self.sharedcell.contents.ctx1[i]=0
self.sharedcell.contents.ctx2[i]=0
self.sharedcell.contents.using[i]=0
if use:
for i in range(10):
if(self.sharedcell.contents.using[i]==0):
self.sharedcell.contents.using[i]=1
self.sharedcell.contents.addr[i]=address
self.sharedcell.contents.ctx1[i]=ctx1
self.sharedcell.contents.ctx2[i]=ctx2
break
def gettextthread(self ): def gettextthread(self ):
text=self.newline.get() text=self.newline.get()
@ -320,8 +408,7 @@ class texthook(basetext ):
return self.runonce_line return self.runonce_line
def end(self): def end(self):
for pid in self.pids: for pid in self.pids:
self.RPC.Detach(pid) self.Luna_Detach(pid)
self.RPC.end()
time.sleep(0.1) time.sleep(0.1)
super().end() super().end()

View File

@ -1,15 +1,11 @@
from ctypes import c_uint,c_bool,POINTER,c_char_p,c_uint64,c_wchar_p,pointer,CDLL,Structure,c_void_p,cast from ctypes import c_uint,c_bool,POINTER,c_char_p,c_uint64,c_wchar_p,pointer,CDLL,Structure,c_void_p,cast
import platform,os import platform,os,gobject
if platform.architecture()[0]=='64bit':
pythonbit='64'
else:
pythonbit='32'
try: try:
if platform.system() != "Windows" or int(platform.version().split('.')[0])<6: if platform.system() != "Windows" or int(platform.version().split('.')[0])<6:
raise Exception() raise Exception()
winrtutilsdll=CDLL(os.path.abspath('./files/plugins/winrtutils{}.dll'.format(pythonbit)) ) winrtutilsdll=CDLL(gobject.GetDllpath(('winrtutils32.dll','winrtutils64.dll')))
except: except:
winrtutilsdll=0 winrtutilsdll=0

View File

@ -1,11 +1,7 @@
from ctypes import c_uint,c_bool,POINTER,c_char_p,c_uint64,c_wchar_p,pointer,CDLL,c_int,Structure,c_void_p,cast,memmove,create_unicode_buffer,create_string_buffer,c_size_t,windll from ctypes import c_uint,c_bool,POINTER,c_char_p,c_uint64,c_wchar_p,pointer,CDLL,c_int,Structure,c_void_p,cast,memmove,create_unicode_buffer,create_string_buffer,c_size_t,windll
import platform,os import os,gobject
if platform.architecture()[0]=='64bit': utilsdll=CDLL(gobject.GetDllpath(('winsharedutils32.dll','winsharedutils64.dll')))
pythonbit='64'
else:
pythonbit='32'
utilsdll=CDLL(os.path.abspath('./files/plugins/winsharedutils{}.dll'.format(pythonbit)) )
_freewstringlist=utilsdll.freewstringlist _freewstringlist=utilsdll.freewstringlist
_freewstringlist.argtypes=POINTER(c_wchar_p),c_uint _freewstringlist.argtypes=POINTER(c_wchar_p),c_uint
@ -77,8 +73,7 @@ def distance(s1,s2):
class mecabwrap: class mecabwrap:
def __init__(self,mecabpath) -> None: def __init__(self,mecabpath) -> None:
self.kks=_mecab_init(mecabpath.encode('utf8'),gobject.GetDllpath('libmecab.dll') )
self.kks=_mecab_init(mecabpath.encode('utf8'),os.path.abspath('./files/plugins/libmecab{}.dll'.format(pythonbit)) )
def __del__(self): def __del__(self):
_mecab_end(self.kks) _mecab_end(self.kks)
def parse(self,text): def parse(self,text):

View File

@ -118,6 +118,8 @@
"isshowhira": false, "isshowhira": false,
"locktools": true, "locktools": true,
"showfanyisource": false, "showfanyisource": false,
"use_yapi":true,
"showfanyi":true,
"autoread": false, "autoread": false,
"show_fenci": false, "show_fenci": false,
"jiamingcolor": "black", "jiamingcolor": "black",
@ -465,7 +467,7 @@
}, },
"_6": { "_6": {
"use": false, "use": false,
"name": "显示/隐藏历史翻译", "name": "显示/隐藏历史翻译和调试输出",
"key1": -1, "key1": -1,
"key2": -1, "key2": -1,
"keystring": "" "keystring": ""

File diff suppressed because one or more lines are too long

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "نص طول المخزن المؤقت", "文本缓冲区长度": "نص طول المخزن المؤقت",
"显示/隐藏历史翻译和调试输出": "عرض / إخفاء تاريخ الترجمة وتصحيح الأخطاء الناتج", "显示/隐藏历史翻译和调试输出": "عرض / إخفاء تاريخ الترجمة وتصحيح الأخطاء الناتج",
"历史翻译和调试输出": "تاريخ الترجمة وتصحيح الأخطاء الناتج", "历史翻译和调试输出": "تاريخ الترجمة وتصحيح الأخطاء الناتج",
"调试输出": "التصحيح الناتج" "调试输出": "التصحيح الناتج",
"显示翻译": "عرض الترجمة",
"使用YAPI注入": "استخدام حقن YAPI"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "文字緩衝區長度", "文本缓冲区长度": "文字緩衝區長度",
"显示/隐藏历史翻译和调试输出": "顯示/隱藏歷史翻譯和調試輸出", "显示/隐藏历史翻译和调试输出": "顯示/隱藏歷史翻譯和調試輸出",
"历史翻译和调试输出": "歷史翻譯和調試輸出", "历史翻译和调试输出": "歷史翻譯和調試輸出",
"调试输出": "調試輸出" "调试输出": "調試輸出",
"显示翻译": "顯示翻譯",
"使用YAPI注入": "使用YAPI注入"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Text buffer length", "文本缓冲区长度": "Text buffer length",
"显示/隐藏历史翻译和调试输出": "Show/hide historical translation and debugging output", "显示/隐藏历史翻译和调试输出": "Show/hide historical translation and debugging output",
"历史翻译和调试输出": "Historical translation and debugging output", "历史翻译和调试输出": "Historical translation and debugging output",
"调试输出": "Debugging output" "调试输出": "Debugging output",
"显示翻译": "Display translation",
"使用YAPI注入": "Using YAPI injection"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Longitud del colchón de texto", "文本缓冲区长度": "Longitud del colchón de texto",
"显示/隐藏历史翻译和调试输出": "Mostrar / ocultar la traducción histórica y depurar la salida", "显示/隐藏历史翻译和调试输出": "Mostrar / ocultar la traducción histórica y depurar la salida",
"历史翻译和调试输出": "Traducción histórica y salida de depuración", "历史翻译和调试输出": "Traducción histórica y salida de depuración",
"调试输出": "Salida de depuración" "调试输出": "Salida de depuración",
"显示翻译": "Mostrar traducción",
"使用YAPI注入": "Inyección con Yapi"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Longueur du tampon de texte", "文本缓冲区长度": "Longueur du tampon de texte",
"显示/隐藏历史翻译和调试输出": "Afficher / masquer la traduction historique et la sortie de débogage", "显示/隐藏历史翻译和调试输出": "Afficher / masquer la traduction historique et la sortie de débogage",
"历史翻译和调试输出": "Traduction historique et sortie de débogage", "历史翻译和调试输出": "Traduction historique et sortie de débogage",
"调试输出": "Sortie de débogage" "调试输出": "Sortie de débogage",
"显示翻译": "Afficher la traduction",
"使用YAPI注入": "Injection avec Yapi"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Lunghezza buffer di testo", "文本缓冲区长度": "Lunghezza buffer di testo",
"显示/隐藏历史翻译和调试输出": "Mostra/nasconde l'output storico di traduzione e debug", "显示/隐藏历史翻译和调试输出": "Mostra/nasconde l'output storico di traduzione e debug",
"历史翻译和调试输出": "Risultato storico di traduzione e debug", "历史翻译和调试输出": "Risultato storico di traduzione e debug",
"调试输出": "Debug output" "调试输出": "Debug output",
"显示翻译": "Mostra traduzione",
"使用YAPI注入": "Uso dell'iniezione di YAPI"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "テキストバッファ長", "文本缓冲区长度": "テキストバッファ長",
"显示/隐藏历史翻译和调试输出": "履歴翻訳とデバッグ出力の表示/非表示", "显示/隐藏历史翻译和调试输出": "履歴翻訳とデバッグ出力の表示/非表示",
"历史翻译和调试输出": "履歴翻訳とデバッグ出力", "历史翻译和调试输出": "履歴翻訳とデバッグ出力",
"调试输出": "デバッグ出力" "调试输出": "デバッグ出力",
"显示翻译": "翻訳を表示",
"使用YAPI注入": "YAPI注入を使用する"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "텍스트 버퍼 길이", "文本缓冲区长度": "텍스트 버퍼 길이",
"显示/隐藏历史翻译和调试输出": "히스토리 번역 및 디버그 출력 표시 / 숨기기", "显示/隐藏历史翻译和调试输出": "히스토리 번역 및 디버그 출력 표시 / 숨기기",
"历史翻译和调试输出": "역사 번역 및 디버그 출력", "历史翻译和调试输出": "역사 번역 및 디버그 출력",
"调试输出": "출력 디버그" "调试输出": "출력 디버그",
"显示翻译": "번역 표시",
"使用YAPI注入": "YAPI 주입 사용"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Długość bufora tekstu", "文本缓冲区长度": "Długość bufora tekstu",
"显示/隐藏历史翻译和调试输出": "Pokaż/ukryj historyczne tłumaczenie i wyjście debugowania", "显示/隐藏历史翻译和调试输出": "Pokaż/ukryj historyczne tłumaczenie i wyjście debugowania",
"历史翻译和调试输出": "Historiczne tłumaczenie i debugowanie", "历史翻译和调试输出": "Historiczne tłumaczenie i debugowanie",
"调试输出": "Wyjście debugowania" "调试输出": "Wyjście debugowania",
"显示翻译": "Wyświetl tłumaczenie",
"使用YAPI注入": "Zastosowanie wstrzykiwań YAPI"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Длина буфера текста", "文本缓冲区长度": "Длина буфера текста",
"显示/隐藏历史翻译和调试输出": "Показать / скрыть исторический перевод и отладочный вывод", "显示/隐藏历史翻译和调试输出": "Показать / скрыть исторический перевод и отладочный вывод",
"历史翻译和调试输出": "Исторический перевод и отладка вывода", "历史翻译和调试输出": "Исторический перевод и отладка вывода",
"调试输出": "Отладочный вывод" "调试输出": "Отладочный вывод",
"显示翻译": "Показать перевод",
"使用YAPI注入": "Использовать инъекцию YAPI"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "ความยาวบัฟเฟอร์ข้อความ", "文本缓冲区长度": "ความยาวบัฟเฟอร์ข้อความ",
"显示/隐藏历史翻译和调试输出": "แสดง / ซ่อนการแปลประวัติและการแก้จุดบกพร่องเอาท์พุท", "显示/隐藏历史翻译和调试输出": "แสดง / ซ่อนการแปลประวัติและการแก้จุดบกพร่องเอาท์พุท",
"历史翻译和调试输出": "การแปลประวัติและการแก้จุดบกพร่องเอาท์พุท", "历史翻译和调试输出": "การแปลประวัติและการแก้จุดบกพร่องเอาท์พุท",
"调试输出": "การว่าจ้างเอาท์พุท" "调试输出": "การว่าจ้างเอาท์พุท",
"显示翻译": "แสดงคำแปล",
"使用YAPI注入": "ใช้ YAPI ฉีด"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Metin buffer uzunluğu", "文本缓冲区长度": "Metin buffer uzunluğu",
"显示/隐藏历史翻译和调试输出": "Tarihi çevirimi ve arızasızlandırma çıkışını göster/gizle", "显示/隐藏历史翻译和调试输出": "Tarihi çevirimi ve arızasızlandırma çıkışını göster/gizle",
"历史翻译和调试输出": "Tarihi çeviri ve hata ayıklama çıkışı", "历史翻译和调试输出": "Tarihi çeviri ve hata ayıklama çıkışı",
"调试输出": "Hata ayıklama çıkışı" "调试输出": "Hata ayıklama çıkışı",
"显示翻译": "Çeviri göster",
"使用YAPI注入": "YAPI injeksiyonu kullanıyor"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Довжина текстового буфера", "文本缓冲区长度": "Довжина текстового буфера",
"显示/隐藏历史翻译和调试输出": "Показувати/сховати історичний переклад і вивід зневаджування", "显示/隐藏历史翻译和调试输出": "Показувати/сховати історичний переклад і вивід зневаджування",
"历史翻译和调试输出": "Історічний переклад і вивід зневаджування", "历史翻译和调试输出": "Історічний переклад і вивід зневаджування",
"调试输出": "Вивод зневаджування" "调试输出": "Вивод зневаджування",
"显示翻译": "Показувати переклад",
"使用YAPI注入": "Використання інструкції YAPI"
} }

View File

@ -685,5 +685,7 @@
"文本缓冲区长度": "Chiều dài bộ đệm văn bản", "文本缓冲区长度": "Chiều dài bộ đệm văn bản",
"显示/隐藏历史翻译和调试输出": "Hiển thị/ẩn lịch sử dịch và đầu ra gỡ lỗi", "显示/隐藏历史翻译和调试输出": "Hiển thị/ẩn lịch sử dịch và đầu ra gỡ lỗi",
"历史翻译和调试输出": "Lịch sử dịch và gỡ lỗi đầu ra", "历史翻译和调试输出": "Lịch sử dịch và gỡ lỗi đầu ra",
"调试输出": "Đầu ra gỡ lỗi" "调试输出": "Đầu ra gỡ lỗi",
"显示翻译": "Hiện bản dịch",
"使用YAPI注入": "Sử dụng YAPI Injection"
} }

View File

@ -686,5 +686,6 @@
"历史翻译和调试输出": "", "历史翻译和调试输出": "",
"历史翻译": "", "历史翻译": "",
"调试输出": "", "调试输出": "",
"显示/隐藏历史翻译": "" "显示翻译": "",
"使用YAPI注入": ""
} }

View File

@ -6,27 +6,15 @@ if x86:
nuitkadist=r'..\build\x86\LunaTranslator_main.dist' nuitkadist=r'..\build\x86\LunaTranslator_main.dist'
targetdir=r'..\build\LunaTranslator_x86' targetdir=r'..\build\LunaTranslator_x86'
launch=r'..\plugins\exec\builds\_x86' launch=r'..\plugins\exec\builds\_x86'
badcdlls= [
'libcurl-x64.dll','libmecab64.dll',
'ocr64.dll',
'winsharedutils64.dll','winrtutils64.dll',
r'brotli\x64\brotlicommon.dll',
r'brotli\x64\brotlidec.dll',
]
downlevel=f'C:\Windows\SysWOW64\downlevel' downlevel=f'C:\Windows\SysWOW64\downlevel'
target='LunaTranslator_x86.zip' target='LunaTranslator_x86.zip'
baddll='DLL64'
else: else:
baddll='DLL32'
target='LunaTranslator.zip' target='LunaTranslator.zip'
launch=r'..\plugins\exec\builds\_x64' launch=r'..\plugins\exec\builds\_x64'
nuitkadist=r'..\build\x64\LunaTranslator_main.dist' nuitkadist=r'..\build\x64\LunaTranslator_main.dist'
targetdir=r'..\build\LunaTranslator' targetdir=r'..\build\LunaTranslator'
badcdlls= [
'libcurl.dll','libmecab32.dll',
'ocr32.dll',
'winsharedutils32.dll','winrtutils32.dll',
r'brotli\x86\brotlicommon.dll',
r'brotli\x86\brotlidec.dll',
]
downlevel=f'C:\Windows\system32\downlevel' downlevel=f'C:\Windows\system32\downlevel'
targetdir_in=rf'{targetdir}\LunaTranslator' targetdir_in=rf'{targetdir}\LunaTranslator'
def get_import_table(file_path): def get_import_table(file_path):
@ -62,9 +50,7 @@ for f in [
for f in ['imageformats','platforms','styles']: for f in ['imageformats','platforms','styles']:
os.rename(rf'{targetdir_in}\PyQt5\qt-plugins\{f}',rf'{targetdir_in}\{f}') os.rename(rf'{targetdir_in}\PyQt5\qt-plugins\{f}',rf'{targetdir_in}\{f}')
remove(rf'{targetdir}\files\plugins\{baddll}')
for f in badcdlls:
remove(rf'{targetdir}\files\plugins\{f}')
collect=[] collect=[]
for _dir,_,fs in os.walk(targetdir): for _dir,_,fs in os.walk(targetdir):