Skip to content

Instantly share code, notes, and snippets.

@dkw72n
Last active May 17, 2018 02:55
Show Gist options
  • Select an option

  • Save dkw72n/ec8cfe2a54f48b22f8465b92945bd3c6 to your computer and use it in GitHub Desktop.

Select an option

Save dkw72n/ec8cfe2a54f48b22f8465b92945bd3c6 to your computer and use it in GitHub Desktop.
UE4 string dumper
import struct
def logi(*args):
if args:
fmt, args = args[0], args[1:]
if args:
fmt = fmt % tuple(args)
print '[-] %s' % fmt
def loge(*args):
if args:
fmt, args = args[0], args[1:]
if args:
fmt = fmt % tuple(args)
print '[!] %s' % fmt
for i in traceback.format_exc().split('\n'):
print " ", i
def get_module_base(process, module):
for mo in p.list_modules():
if mo.szModule.lower() == module.lower():
return mo.modBaseAddr
return None
def read_pointer(process, addr):
bytes = process.read_bytes(addr, bytes = 8)
# print "reading pointer: %08x -> %r" % (addr, bytes)
if bytes and len(bytes) == 8:
return struct.unpack('Q', bytes)[0]
return None
def read_float(process, addr):
bytes = process.read_bytes(addr, bytes = 4)
# print "reading pointer: %08x -> %r" % (addr, bytes)
if bytes and len(bytes) == 4:
return struct.unpack('f', bytes)[0]
return None
def read_int32(process, addr):
bytes = process.read_bytes(addr, bytes = 4)
# print "reading pointer: %08x -> %r" % (addr, bytes)
if bytes and len(bytes) == 4:
return struct.unpack('i', bytes)[0]
return None
def read_uint32(process, addr):
bytes = process.read_bytes(addr, bytes = 4)
# print "reading pointer: %08x -> %r" % (addr, bytes)
if bytes and len(bytes) == 4:
return struct.unpack('I', bytes)[0]
return None
def read_cstring(process, addr):
STEP = 32
ret = ''
off = 0
while True:
part = process.read_bytes(addr + off, bytes = STEP)
if not part:
break
end = part.find('\x00')
if end != -1:
ret += part[:end]
break
ret += part
off += STEP
return ret
def dump_range(proc, base, left, right):
print "%016x" % base
for off in range(left, right, 8):
print " %08x %016x %10.5g %10.5g %16d %16d" % (
off,
read_pointer(proc, base + off),
read_float(proc, base + off),
read_float(proc, base + off + 4),
read_int32(proc, base + off),
read_int32(proc, base + off + 4),
)
#coding: utf8
from memorpy import *
from shrutils import *
import struct
"""
在内存中搜索 UE4 的全局字符串表入口.
全局表结构:
{
FNameEntry** Buckets[128]; // 0x000
int32_t nEntries; // 0x400
int32_t nBuckets; // 0x404
}
Buckets[i] 指向一个 FNameEntry* Names[0x4000]
FNameEntry 结构
{
int32_t Index; //0x00
int32_t dummy; //0x04
FNameEntry* Next; //0x08
TCHAR data[0]; //0x10
}
Index = (iBucket * 0x4000 + iName) * 2 + (1 if wchar else 0)
"""
IMAGE_NAME = 'VehicleDemo.exe'
def get_hex_of(bytes):
return ' '.join(map(lambda x: "%02x" % ord(x), bytes))
Candidates = dict()
def try_get_names_addr_from_str(mw, addr):
p_addr_entry = addr - 0x10
idx = read_uint32(mw.process, p_addr_entry)
print "trying", hex(int(p_addr_entry))
print "idx = ", idx
y = idx / 2 % 0x4000
x = idx / 2 / 0x4000
print "searching for ", get_hex_of(struct.pack('Q', int(p_addr_entry)))
p_entry_array_addrs = mw.mem_search(struct.pack('Q', int(p_addr_entry)))
for entry_item in p_entry_array_addrs:
guess_addr = entry_item - (y * 8)
p_name_array_addrs = mw.mem_search(struct.pack('Q', int(guess_addr)))
for name_item in p_name_array_addrs:
guess = name_item - x * 8
print "guessing:", hex(int(guess)), read_int32(mw.process, guess + 0x400), read_int32(mw.process, guess + 0x404)
Candidates[int(guess)] = Candidates.get(int(guess), 0) + 1
pass
def guess_forward(mw, guess, addr):
print "guess_forward:", hex(guess), "->", hex(int(addr))
p_addr_entry = addr - 0x10
idx = read_uint32(mw.process, p_addr_entry)
y = idx / 2 % 0x4000
x = idx / 2 / 0x4000
bucket = read_pointer(mw.process, guess + x * 8)
entry = read_pointer(mw.process, bucket + y * 8)
return entry == int(p_addr_entry)
def dump_all_string(mw, addr):
T = read_int32(mw.process, addr + 0x400)
for i in range(T):
x = i / 0x4000
y = i % 0x4000
bucket = read_pointer(mw.process, addr + x * 8)
entry = read_pointer(mw.process, bucket + y * 8)
idx = read_int32(mw.process, entry)
if idx is None:
continue
print "%08x %08x %r" % (idx, i, read_cstring(mw.process, entry + 0x10))
if __name__ == '__main__':
PID = int(sys.argv[1])
#with MemWorker(name=IMAGE_NAME) as mw:
with MemWorker(pid = int() as mw:
print "process:", mw.process
i = 0
#for addr in mw.mem_search("Default__ShooterPlayer"):
for addr in mw.mem_search("Default__ActorComponent"):
if i > 5: break
if int(addr) % 8 != 0: continue
i += 1
good_candidate = None
for candidate in Candidates:
if guess_forward(mw, candidate, addr):
print "guess forward successfully"
good_candidate = candidate
break
if good_candidate:
Candidates[good_candidate] += 1
else:
try_get_names_addr_from_str(mw, addr)
if Candidates:
print Candidates
best = max(Candidates, key=lambda x:Candidates[x])
dump_all_string(mw, best)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment