Skip to content

Instantly share code, notes, and snippets.

@dkw72n
Created December 7, 2018 08:13
Show Gist options
  • Select an option

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

Select an option

Save dkw72n/4a66672b5e57f7fcecd3173a2078d7f2 to your computer and use it in GitHub Desktop.
no description
#coding: utf8
import sys
import os
from collections import Counter
import argparse
VERBOSE = 1
STDERR = sys.stderr
def excepthook(*args):
print >> STDERR, 'caught'
print >> STDERR, args
sys.excepthook = excepthook
def readInt16(buf, off):
return buf[off+1] * 0x100 + buf[off]
def readInt32(buf, off):
return buf[off+3] * 0x1000000 + buf[off+2]* 0x10000 + buf[off+1] * 0x100 + buf[off]
def readString(buf, off):
pos = buf[off:].index(0)
return ''.join(map(chr, buf[off: off + pos]))
def ProgramHeaders(elf):
phoff = readInt32(elf, 0x1c)
phnum = readInt16(elf, 0x2c)
#print "phoff", phoff
#print "phnum", phnum
for i in range(phnum):
yield elf[phoff + i * 32: phoff + i * 32 + 32]
def SectionHeaders(elf):
e_shoff = readInt32(elf, 0x20)
e_shentsize = readInt16(elf, 0x2E)
e_shnum = readInt16(elf, 0x30)
if VERBOSE > 1: print "e_shoff", e_shoff, "e_shnum", e_shnum
for i in range(e_shnum):
ret = elf[e_shoff + i * e_shentsize: e_shoff + i * e_shentsize + e_shentsize]
if VERBOSE > 1: print ret
yield ret
def PrintProgramHeaders():
for ph in ProgramHeaders(elf):
ty = readInt32(ph, 0x00)
offset = readInt32(ph, 0x04)
vaddr = readInt32(ph, 0x08)
filesz = readInt32(ph, 0x10)
memsz = readInt32(ph, 0x14)
flag = readInt32(ph, 0x18)
# print "%6d %08x %d %d %d" % (ty, offset, filesz, memsz, flag & 2)
if VERBOSE > 1: print "from %08x to %08x" % (offset, offset + filesz)
def arg_file(fn):
assert os.path.isfile(fn)
return fn
def main(opts):
with open(opts.input, "rb") as fp:
elf = map(ord, fp.read())
shs = []
shstrtab = None
for sh in SectionHeaders(elf):
sh_name = readInt32(sh, 0x0)
sh_type = readInt32(sh, 0x4)
sh_offset = readInt32(sh, 0x10)
sh_size = readInt32(sh, 0x14)
# print sh
if VERBOSE > 1: print "name:", sh_name, "type: %x" % sh_type
shs.append([sh_name, sh_type, sh_offset, sh_size])
if sh_type == 3 and sh_name == 1: # shstrtab
if VERBOSE > 1: print ''.join(map(chr, elf[sh_offset: sh_offset + sh_size]))
shstrtab = elf[sh_offset: sh_offset + sh_size]
#print shstrtab
for sh in shs:
name = readString(shstrtab, sh[0])
if name == '.text' or name == '.rodata':
if VERBOSE > 0: print name, "%08x: len=%d" % (sh[2], sh[3])
c = Counter()
for j in range(sh[2], sh[2] + sh[3]):
c[elf[j]] += 1
#elf[j] ^= 0xe9
key = c.most_common(1)[0][0]
if VERBOSE > 0: print "key = 0x%x" % key
for j in range(sh[2], sh[2] + sh[3]):
elf[j] ^= key
if os.path.exists(opts.output) and not opts.force:
print u"已存在, 确认覆盖请输入 Y"
comfirmation = raw_input()
if comfirmation != "Y":
#print "%r" % comfirmation
print "Abort"
return
with open(opts.output, "wb") as fp:
fp.write(''.join(map(chr, elf)))
print "successful"
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', type=arg_file, required=True)
parser.add_argument('-o', '--output', default='dump.so')
parser.add_argument('-f', '--force', action='store_true')
opts = parser.parse_args()
main(opts)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment