mirror of https://github.com/Shizmob/smol
add smoldd
This commit is contained in:
parent
b08e23a16c
commit
560ce8c0f2
|
@ -0,0 +1,146 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
import struct
|
||||
import sys
|
||||
|
||||
from smolshared import *
|
||||
|
||||
def readbyte(blob, off):
|
||||
return struct.unpack('<B', blob[off:off+1])[0], (off+1)
|
||||
|
||||
def readint(blob, off):
|
||||
return struct.unpack('<I', blob[off:off+4])[0], (off+4)
|
||||
|
||||
def readlong(blob, off):
|
||||
return struct.unpack('<Q', blob[off:off+8])[0], (off+8)
|
||||
|
||||
def readstr(blob, off):
|
||||
text = bytearray()
|
||||
while True:
|
||||
char, off = readbyte(blob, off)
|
||||
if char == 0:
|
||||
break
|
||||
|
||||
text.append(char)
|
||||
|
||||
return text.decode('utf-8'), off
|
||||
|
||||
def find_libs(bits, libname):
|
||||
dirs = os.environ['LD_LIBRARY_PATH'].split(':')
|
||||
dirs += ['/usr/lib','/lib']
|
||||
|
||||
for d in dirs:
|
||||
for f in glob.glob(glob.escape(d+str(bits)+'/'+libname)+'*'):
|
||||
yield f
|
||||
|
||||
def build_hashtab(scanelf_bin, lib):
|
||||
out = subprocess.check_output([scanelf_bin, '-B', '-F', '%s', '-s', '%pd%*', lib],
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
blah = set(out.decode('utf-8').split('\n'))
|
||||
ret = dict({})
|
||||
|
||||
for x in blah:
|
||||
y = x.split()
|
||||
if len(y) != 7:
|
||||
continue
|
||||
ret[hash_djb2(y[6])] = y[6]
|
||||
|
||||
return ret
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('input', type=argparse.FileType('rb'),
|
||||
default=sys.stdin.buffer, help="input file")
|
||||
parser.add_argument('--scanelf',
|
||||
default=shutil.which('scanelf'), help="scanelf binary")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
blob = args.input.read()
|
||||
|
||||
machnum = struct.unpack('<H', blob[18:18+2])[0]
|
||||
|
||||
is32bit = machnum == archmagic['i386']
|
||||
|
||||
phoff, phsz, phnum = 0, 0, 0
|
||||
if is32bit:
|
||||
phoff = struct.unpack('<I', blob[28:28+4])[0]
|
||||
phsz = struct.unpack('<H', blob[42:42+2])[0]
|
||||
phnum = struct.unpack('<H', blob[44:52+2])[0]
|
||||
elif machnum == archmagic['x86_64']:
|
||||
phoff = struct.unpack('<Q', blob[32:32+8])[0]
|
||||
phsz = struct.unpack('<H', blob[54:54+2])[0]
|
||||
phnum = struct.unpack('<H', blob[56:56+2])[0]
|
||||
else:
|
||||
eprintf("Unknown architecture " + str(machnum))
|
||||
sys.exit(1)
|
||||
|
||||
for i in range(phnum):
|
||||
off = phoff + i * phsz
|
||||
#print(hex(off))
|
||||
|
||||
ptyp, poff, pva, ppa, pfsz, pmsz, pfl, pal = 0,0,0,0,0,0,0,0
|
||||
if is32bit:
|
||||
ptyp, poff, pva, ppa, pfsz, pmsz, pfl, pal = \
|
||||
struct.unpack('<ILLLIIII', blob[off:off+phsz])
|
||||
else:
|
||||
ptyp, pfl, poff, pva, ppa, pfsz, pmsz, pal = \
|
||||
struct.unpack('<IIQQQQQQ', blob[off:off+phsz])
|
||||
|
||||
if ptyp != 2: # PT_DYNAMIC
|
||||
continue
|
||||
|
||||
#print(hex(poff))
|
||||
|
||||
# right after the dynamic section, the smol 'symtab'/'hashtab' is found
|
||||
#
|
||||
# note that on i386, every lib name is followed by an E9 byte
|
||||
# if the next libname/first byte of the hash is null, the table has
|
||||
# come to an end.
|
||||
|
||||
j = poff
|
||||
strtaboff = 0
|
||||
while j < poff + pfsz:
|
||||
tag, j = (readint(blob, j) if is32bit else readlong(blob, j))
|
||||
ptr, j = (readint(blob, j) if is32bit else readlong(blob, j))
|
||||
|
||||
if tag == 5: # DT_STRTAB
|
||||
strtaboff = ptr
|
||||
elif tag == 1: # DT_NEEDED
|
||||
bakoff = j
|
||||
|
||||
smoltaboff = strtaboff + ptr - (pva - poff)
|
||||
j = smoltaboff
|
||||
|
||||
libname, j = readstr(blob, j)
|
||||
if len(libname) == 0:
|
||||
break
|
||||
|
||||
sys.stdout.write("* " + libname)
|
||||
|
||||
libs = list(find_libs(32 if is32bit else 64, libname))
|
||||
print(" -> NOT FOUND" if len(libs) == 0 else (" -> " + libs[0]))
|
||||
ht = dict({}) if len(libs) == 0 else build_hashtab(args.scanelf, libs[0])
|
||||
|
||||
while True:
|
||||
hashv, j = (readint(blob, j) if is32bit else readlong(blob, j))
|
||||
|
||||
if (hashv & 0xFF) == 0:
|
||||
break
|
||||
|
||||
sys.stdout.write(" * " + hex(hashv))
|
||||
print(" -> NOT FOUND" if hashv not in ht else (" -> " + ht[hashv]))
|
||||
|
||||
j = bakoff
|
||||
|
||||
break
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -3,12 +3,6 @@ import sys
|
|||
|
||||
from smolshared import *
|
||||
|
||||
def hash_djb2(s):
|
||||
h = 5381
|
||||
for c in s:
|
||||
h = (h * 33 + ord(c)) & 0xFFFFFFFF
|
||||
return h
|
||||
|
||||
def output_x86(libraries, outf):
|
||||
outf.write('; vim: set ft=nasm:\n') # be friendly
|
||||
outf.write('bits 32\n')
|
||||
|
|
|
@ -60,9 +60,9 @@ def is_valid_elf(f):
|
|||
|
||||
def find_lib(spaths, wanted):
|
||||
for p in spaths:
|
||||
for f in glob.glob(glob.escape(p) + '/lib' + wanted + '.so*'):
|
||||
for f in glob.glob(glob.escape(p + '/lib' + wanted) + '.so*'):
|
||||
if os.path.isfile(f) and is_valid_elf(f): return f
|
||||
for f in glob.glob(glob.escape(p) + '/' + wanted + '.so*'):
|
||||
for f in glob.glob(glob.escape(p + '/' + wanted) + '.so*'):
|
||||
if os.path.isfile(f) and is_valid_elf(f): return f
|
||||
#for f in glob.glob(glob.escape(p) + '/lib' + wanted + '.a' ): return f
|
||||
#for f in glob.glob(glob.escape(p) + '/' + wanted + '.a' ): return f
|
||||
|
|
|
@ -6,5 +6,11 @@ archmagic = {
|
|||
'x86_64': 62, 62: 'x86_64',
|
||||
}
|
||||
|
||||
def hash_djb2(s):
|
||||
h = 5381
|
||||
for c in s:
|
||||
h = (h * 33 + ord(c)) & 0xFFFFFFFF
|
||||
return h
|
||||
|
||||
def eprintf(*args, **kwargs): print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
|
Loading…
Reference in New Issue