def main(instrument=False): """ Transform malformed code and add main symbol :param instrument: True to insert instrumentation code """ with open("final.s") as f: lines = f.readlines() if ELF_utils.elf_exe(): main_symbol1 = '' with open('main.info') as f: main_symbol1 = f.readline().strip() if main_symbol1 != '': def helpf(l): if '__gmon_start__' in l: l = '' elif 'lea 0x7FFFFFFC(,%ebx,0x4),%edi' in l: l = l.replace('0x7FFFFFFC', '0x7FFFFFFFFFFFFFFC') elif 'movzbl $S_' in l: l = l.replace('movzbl $S_', 'movzbl S_') elif 'jmpq ' in l and '*' not in l: l = l.replace('jmpq ', 'jmp ') elif 'repz retq' in l: # to solve the error of 'expecting string instruction after `repz' l = l.replace('repz retq', 'retq') elif 'repz ret' in l: l = l.replace('repz ret', 'ret') elif 'nop' in l: l = l.replace('nop', ' ') if main_symbol1 + ' :' in l: rep = '.globl main\nmain : ' if instrument: rep += '\n'.join( map(lambda e: e['plain'].beforemain, config.instrumentors)) + '\n' l = l.replace(main_symbol1 + ' : ', rep) elif main_symbol1 in l: l = l.replace(main_symbol1, 'main') return l lines = map(helpf, lines) with open("final.s", 'w') as f: f.writelines(lines) if instrument: f.write('\n'.join( map(lambda e: e['plain'].aftercode, config.instrumentors)) + '\n') if os.path.isfile('inline_symbols.txt'): inline_update.main()
def picprocess32(filepath): """ PC relative operation in x86 32 bit code such as: call 804c452 <__x86.get_pc_thunk.bx> add $0x2b8e,%ebx mov $0x10, (%ebx) This operation usually loads into %ebx the address of the _GLOBAL_OFFSET_TABLE_ Further adjustments are operated in the analysis phase :param filepath: path to target executable """ if ELF_utils.elf_32() and ELF_utils.elf_exe() and not ELF_utils.elf_arm(): text_process_strip(filepath)
def main(filepath, instrument=False): """ Init processing :param filepath: path to executable :param instrument: True to apply instrumentation """ if ELF_utils.elf_strip() and ELF_utils.elf_exe(): init = Init(filepath) init.disassemble() init.process() init.ailProcess(instrument) else: sys.stderr.write( 'Error: binary is not stripped or is a shared library\n')
def main_discover(filename): """ Find main function address and store it to file :param filename: path to target executable """ os.system('file ' + filename + ' > elf.info') if ELF_utils.elf_exe(): os.system(config.objdump + ' -Dr -j .text ' + filename + ' > ' + filename + '.temp') with open(filename + '.temp') as f: lines = f.readlines() ll = len(lines) main_symbol = "" if config.arch == config.ARCH_X86: for i in xrange(ll): l = lines[i] # when not using O2 to compile the original binary, we will remove all the _start code, # including the routine attached on the original program. In that case, we can not discover the # main function if "<__libc_start_main@plt>" in l: main_symbol = lines[i-1].split()[-1] if ELF_utils.elf_32() \ else lines[i-1].split()[-1].split(',')[0] if main_symbol == '%eax': # to fit gcc-4.8 -m32, the address is mov to %eax, then push to stack main_symbol = lines[i - 2].split()[-1].split( ',')[0].split('0x')[1] else: main_symbol = main_symbol.split('0x')[1] break #lines[i-1] = lines[i-1].replace(main_symbol, "main") #main_symbol = main_symbol[1:].strip() #print main_symbol ## Some of the PIC code/module rely on typical pattern to locate ## such as: ## 804c460: push %ebx ## 804c461: call 804c452 <__i686.get_pc_thunk.bx> ## 804c466: add $0x2b8e,%ebx ## 804c46c: sub $0x18,%esp ## What we can do this pattern match `<__i686.get_pc_thunk.bx>` and calculate ## the address by plusing 0x2b8e and 0x804c466, which equals to the begin address of GOT.PLT table ## symbols can be leveraged in re-assemble are ## _GLOBAL_OFFSET_TABLE_ == ** .got.plt ** ## .... elif config.arch == config.ARCH_ARMT: ## 1035c: 4803 ldr r0, [pc, #12] ; (1036c <_start+0x28>) ## 1035e: 4b04 ldr r3, [pc, #16] ; (10370 <_start+0x2c>) ## 10360: f7ff efde blx 10320 <__libc_start_main@plt> ## 10364: f7ff efe8 blx 10338 <abort@plt> ## ... ## 1036c: 0001052d for i in xrange(ll): l = lines[i] if '<__libc_start_main@plt>' in l: j = i - 1 while j > 0: if 'ldr' in lines[j] and 'r0' in lines[j]: pcraddr = lines[j].split( ';')[1].strip().split()[0][1:] break j -= 1 j = i + 1 while j < ll: if lines[j].strip().startswith(pcraddr): main_symbol = lines[j].split()[1] if len(main_symbol) < 8: main_symbol = lines[j + 1].split()[1] + main_symbol main_symbol = int(main_symbol.lstrip('0'), 16) & (-2) main_symbol = '%X' % main_symbol break j += 1 break else: raise Exception('Unknown arch') with open("main.info", 'w') as f: f.write('S_0x' + main_symbol.upper() + '\n')