Last active
November 14, 2021 04:25
-
-
Save ess7/1ae08640ea22b92764acd1ad84516156 to your computer and use it in GitHub Desktop.
Dump NSEEL functions in jsfx.dll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ctypes import * | |
import struct | |
import re | |
assert RPR_GetAppVersion()[-4:] == '/x64' | |
def console(s): | |
RPR_ShowConsoleMsg(str(s) + '\n') | |
class MODULEINFO(Structure): | |
_fields_ = [ | |
('lpBaseOfDll', c_void_p), | |
('SizeOfImage', c_ulong), | |
('EntryPoint', c_void_p) | |
] | |
kernel32 = windll.kernel32 | |
kernel32.GetCurrentProcess.restype = c_void_p | |
kernel32.GetModuleHandleA.argtypes = [c_char_p] | |
kernel32.GetModuleHandleA.restype = c_void_p | |
kernel32.K32GetModuleInformation.argtypes = [c_void_p, c_void_p, c_void_p, c_ulong] | |
kernel32.K32GetModuleInformation.restype = c_long | |
MIN_MATCH = 7 | |
MAX_MATCH = 32 | |
def longest_match(haystack, needle): | |
longest = None | |
where = None | |
for length in range(MIN_MATCH, len(needle)): | |
i = haystack.find(needle[:length]) | |
if i >= 0: | |
where = i | |
longest = length | |
else: | |
break | |
if where is not None and \ | |
haystack.find(needle[:longest], where+longest) == -1: # no other match | |
return where, longest | |
else: | |
return None, None | |
RPR_ShowConsoleMsg('') | |
reaper = kernel32.GetModuleHandleA(None) | |
jsfx = kernel32.GetModuleHandleA(b'jsfx.dll') | |
jsfx_modinfo = MODULEINFO() | |
reaper_modinfo = MODULEINFO() | |
kernel32.K32GetModuleInformation(kernel32.GetCurrentProcess(), reaper, addressof(reaper_modinfo), sizeof(reaper_modinfo)) | |
kernel32.K32GetModuleInformation(kernel32.GetCurrentProcess(), jsfx, addressof(jsfx_modinfo), sizeof(jsfx_modinfo)) | |
reaper_bin = string_at(reaper_modinfo.lpBaseOfDll, reaper_modinfo.SizeOfImage) | |
jsfx_bin = string_at( jsfx_modinfo.lpBaseOfDll, jsfx_modinfo.SizeOfImage) | |
# find function table in reaper.exe | |
''' | |
from 6.40 | |
140573ec5 48 8d 15 14 aa 5b 00 LEA RDX,[function_table] | |
140573ecc 41 b8 e9 00 00 00 MOV R8D,0x.... (table size) | |
140573ed2 41 b9 10 00 00 00 MOV R9D,0x10 | |
140573ed8 e8 e3 b2 3a 00 CALL ... | |
''' | |
for match in re.finditer( | |
b'\x48\x8d\x15(?P<rip_ofs>....)' | |
b'\x41\xb8(?P<table_size>..)\x00\x00' | |
b'\x41\xb9\x10\x00\x00\x00' | |
b'\xe8', | |
reaper_bin, re.DOTALL): | |
function_table_addr = reaper_modinfo.lpBaseOfDll + \ | |
match.start('rip_ofs') + 4 + \ | |
struct.unpack('<l', match.group('rip_ofs'))[0] | |
table_size = struct.unpack('<H', match.group('table_size'))[0] | |
break | |
console('function table 0x%x\n' % function_table_addr) | |
functions = [] | |
for i in range(table_size): | |
table_entry = string_at(function_table_addr + 16*i, 16) | |
name_addr, func_addr = struct.unpack('<QQ', table_entry) | |
functions.append((str(string_at(name_addr), 'ascii'), func_addr)) | |
# dump all undocumented functions | |
#for name, addr in functions: | |
# console('{:40} 0x{:05x}'.format(name, addr)) | |
console('{:29} {} {}'.format('function name', 'jsfx RVA', 'length')) | |
for name, addr in functions: | |
pattern = string_at(addr, MAX_MATCH) | |
jsfx_addr, length = longest_match(jsfx_bin, pattern) | |
if jsfx_addr is not None and 'nseel' in name.lower(): | |
console('{:29} 0x{:05x} {:2d}'.format(name, jsfx_addr, length)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment