def _mov_thumb(dst, src): if not pwn.isint(src): return "mov %s, %s" % (dst, src) srcu = src & 0xffffffff srcs = srcu - 2 * (srcu & 0x80000000) if srcu == 0: return 'eor %s, %s' % (dst, dst) if srcu < 256: return 'mov %s, #%d' % (dst, src) if -256 < srcs < 0: return 'eor %s, %s\nsub %s, #%d' % (dst, dst, dst, -srcs) shift1 = 0 while (1 << shift1) & src == 0: shift1 += 1 if (0xff << shift1) & src == src: if shift1 < 4: return 'mov %s, #%d\nlsl %s, #4\nlsr %s, #%d' % ( dst, src >> shift1, dst, dst, 4 - shift1) return 'mov %s, #%d\nlsl %s, #%d' % (dst, src >> shift1, dst, shift1) shift2 = 8 while (1 << shift2) & src == 0: shift2 += 1 if ((0xff << shift2) | 0xff) & src == src: return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d' % ( dst, src >> shift2, dst, shift2, dst, src & 0xff) shift3 = shift1 + 8 while (1 << shift3) & src == 0: shift3 += 1 if ((0xff << shift1) | (0xff << shift3)) & src == src: return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d\nlsl %s, #%d' % ( dst, src >> shift3, dst, shift3 - shift1, dst, (src >> shift1) & 0xff, dst, shift1) id = pwn.randoms(32, only=string.ascii_lowercase) if (src & 0xFF000000 == 0x0): src = src | 0xFF000000 extra = ''.join([ "lsl %s, #8" % dst, "lsr %s, #8" % dst, ]) return '\n'.join([ "ldr %s, %s" % (dst, id), "b %s_after" % id, "%s: .word %d" % (id, src), "%s_after:" % id, extra ])
def _mov_thumb(dst, src): if not pwn.isint(src): return "mov %s, %s" % (dst, src) srcu = src & 0xffffffff srcs = srcu - 2 * (srcu & 0x80000000) if srcu == 0: return 'eor %s, %s' % (dst, dst) if srcu < 256: return 'mov %s, #%d' % (dst, src) if -256 < srcs < 0: return 'eor %s, %s\nsub %s, #%d' % (dst, dst, dst, -srcs) shift1 = 0 while (1 << shift1) & src == 0: shift1 += 1 if (0xff << shift1) & src == src: if shift1 < 4: return 'mov %s, #%d\nlsl %s, #4\nlsr %s, #%d' % (dst, src >> shift1, dst, dst, 4-shift1) return 'mov %s, #%d\nlsl %s, #%d' % (dst, src >> shift1, dst, shift1) shift2 = 8 while (1 << shift2) & src == 0: shift2 += 1 if ((0xff << shift2) | 0xff) & src == src: return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d' % (dst, src >> shift2, dst, shift2, dst, src & 0xff) shift3 = shift1 + 8 while (1 << shift3) & src == 0: shift3 += 1 if ((0xff << shift1) | (0xff << shift3)) & src == src: return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d\nlsl %s, #%d' % (dst, src >> shift3, dst, shift3 - shift1, dst, (src >> shift1) & 0xff, dst, shift1) id = pwn.randoms(32, only = string.ascii_lowercase) if (src & 0xFF000000 == 0x0): src = src | 0xFF000000 extra = ''.join([ "lsl %s, #8" % dst, "lsr %s, #8" % dst, ]) return '\n'.join([ "ldr %s, %s" % (dst, id), "b %s_after" % id, "%s: .word %d" % (id, src), "%s_after:" % id, extra])
def _clookup_real(consts): import string magic = pwn.randoms(32, only = string.ascii_lowercase) magic_ = '\n%s\n' % magic dat = magic_.join([''] + consts) output = pwn.asm(dat, emit_asm = 1) output_ = [line.strip() for line in output.split(magic)] if len(output_) != len(consts) + 1: raise Exception("Unknown output format:\n%s" % output) return output_[1:]
def _mov_thumb(dst, src): if not isinstance(src, int): return "mov %s, %s" % (dst, src) srcu = src & 0xffffffff srcs = srcu - 2 * (srcu & 0x80000000) if srcu == 0: return 'eor %s, %s' % (dst, dst) if srcu < 256: return 'mov %s, #%d' % (dst, src) if -256 < srcs < 0: return 'eor %s, %s\nsub %s, #%d' % (dst, dst, dst, -srcs) shift1 = 0 while (1 << shift1) & src == 0: shift1 += 1 if (0xff << shift1) & src == src: if shift1 < 4: return 'mov %s, #%d\nlsl %s, #4\nlsr %s, #%d' % (dst, src >> shift1, dst, dst, 4-shift1) return 'mov %s, #%d\nlsl %s, #%d' % (dst, src >> shift1, dst, shift1) shift2 = 8 while (1 << shift2) & src == 0: shift2 += 1 if ((0xff << shift2) | 0xff) & src == src: return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d' % (dst, src >> shift2, dst, shift2, dst, src & 0xff) shift3 = shift1 + 8 while (1 << shift3) & src == 0: shift3 += 1 if ((0xff << shift1) | (0xff << shift3)) & src == src: return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d\nlsl %s, #%d' % (dst, src >> shift3, dst, shift3 - shift1, dst, (src >> shift1) & 0xff, dst, shift1) id = pwn.randoms(32, only = string.ascii_lowercase)
def _mov_arm(dst, src): import string if not pwn.isint(src): return "mov %s, %s" % (dst, src) if len(asm("ldr %s, =%d" % (dst, src))) == 4: return "ldr %s, =%d" % (dst, src) srcu = src & 0xffffffff srcn = ~src & 0xffffffff for n, op in zip([srcu, srcn], ['mov', 'mvn']): shift1 = 0 while (0x03 << shift1) & n == 0: shift1 += 2 shift2 = shift1 + 8 while (0x03 << shift2) & n == 0: shift2 += 2 if n == (n & (0xff << shift1)) + (n & (0xff << shift2)): return '\n'.join([ "// mov %s, #%d" % (dst, src), "%s %s, #%d" % (op, dst, (n & (0xff << shift1))), "%s %s, #%d" % ("eor", dst, (n & (0xff << shift2))) ]) id = pwn.randoms(32, only=string.ascii_lowercase) return '\n'.join([ "ldr %s, %s" % (dst, id), "b %s_after" % id, "%s: .word %d" % (id, src), "%s_after:" % id ])
def _mov_arm(dst, src): import string if not isinstance(src, int): return "mov %s, %s" % (dst, src) if len(asm("ldr %s, =%d" % (dst, src))) == 4: return "ldr %s, =%d" % (dst, src) srcu = src & 0xffffffff srcn = ~src & 0xffffffff for n, op in zip([srcu, srcn], ['mov', 'mvn']): shift1 = 0 while (0x03 << shift1) & n == 0: shift1 += 2 shift2 = shift1 + 8 while (0x03 << shift2) & n == 0: shift2 += 2 if n == (n & (0xff << shift1)) + (n & (0xff << shift2)): return '\n'.join([ "// mov %s, #%d" % (dst, src), "%s %s, #%d" % (op, dst, (n & (0xff << shift1))), "%s %s, #%d" % ("eor", dst, (n & (0xff << shift2))) ]) id = pwn.randoms(32, only = string.ascii_lowercase) return '\n'.join([ "ldr %s, %s" % (dst, id), "b %s_after" % id, "%s: .word %d" % (id, src), "%s_after:" % id])
def _asm(target_arch, target_os, code_blocks, emit_asm=0, keep_tmp=False): import pwn.internal.shellcode_helper as H import os.path, tempfile, subprocess, string, shutil if target_arch == None: raise Exception('You need to set the architecture with context') tmpdir = tempfile.mkdtemp(prefix='pwn-asm-') def path(s): return os.path.join(tmpdir, s) try: magic = pwn.randoms(32, only=string.ascii_lowercase) code = [] cpp = ['cpp', '-nostdinc', '-undef', '-w'] if pwn.DEBUG: cpp += ['-D', 'DEBUG'] if target_os != None: include = os.path.join(pwn.installpath, 'pwn', 'include', target_os) cpp += ['-I', include] if target_os == 'linux': if os.path.isfile(os.path.join(include, target_arch + '.h')): cpp += ['-I', os.path.join(include, 'diet')] code += ['#include <%s.h>' % target_arch] elif target_os == 'freebsd': code += ['#include <common.h>'] code += [magic] if target_arch not in ['i386', 'amd64']: code += ['.section .shellcode,"ax"'] asm_extra = [] if target_arch == 'arm': code += ['.arm'] elif target_arch == 'thumb': code += ['.thumb'] target_arch = 'arm' elif target_arch == 'i386': code += ['bits 32'] elif target_arch == 'amd64': code += ['bits 64'] elif target_arch in ['mips', 'mipsel']: code += ['.set mips2'] code += ['.set noreorder'] if target_arch == 'mips': asm_extra += ['--EB'] else: asm_extra += ['--EL'] target_arch = 'mips' code += code_blocks code = '\n'.join(code) if target_arch in ['i386', 'amd64']: assembler = ['nasm', '-Ox'] + asm_extra objcopy = ['objcopy'] else: assembler = [ os.path.join(pwn.installpath, 'binutils', target_arch + '-as') ] + asm_extra if not os.path.isfile(assembler[0]): raise Exception( 'Could not find the gnu assembler for this architecture: %s' % target_arch) objcopy = [ os.path.join(pwn.installpath, 'binutils', 'promisc-objcopy') ] objcopy += ['-j.shellcode', '-Obinary'] if emit_asm == 2: output = [] output += [ "/*", " Assemble with:", " %s [input] -o [input].tmp1" % ' '.join(cpp), " sed -e '0,/^%s$/d' [input].tmp1 > [input].tmp2" % magic, " %s [input].tmp2 -o [input].tmp3" % ' '.join(assembler) ] if target_arch not in ['i386', 'amd64']: output += [" %s [input].tmp3 [output]" % ' '.join(objcopy)] output += ["*/", "", code] return '\n'.join(output) pwn.write(path('step1'), code) _run(cpp + [path('step1'), path('step2')]) code = pwn.read(path('step2')) _code = code.split('\n' + magic + '\n') if len(_code) != 2: raise Exception("The output from cpp was weird:\n%s" % code) code = _code[1] if emit_asm == 1: output = [] if target_arch in ['i386', 'amd64']: output += [ ';; Assemble with:', ';; %s <input> -o <output>' % ' '.join(assembler) ] else: output += [ "/*", " Assemble with:", ' %s <input> -o <input>.tmp' % ' '.join(assembler), ' %s [input].tmp [output]' % ' '.join(objcopy), '*/', ] output += ["", code] return '\n'.join(output) pwn.write(path('step3'), code) _run(assembler + ['-o', path('step4'), path('step3')]) if target_arch in ['i386', 'amd64']: return pwn.read(path('step4')) # Sanity check for seeing if the output has relocations relocs = subprocess.check_output(['readelf', '-r', path('step4')]).strip() if len(relocs.split('\n')) > 1: raise Exception('There were relocations in the shellcode:\n\n%s' % relocs) _run(objcopy + [path('step4'), path('step5')]) return pwn.read(path('step5')) finally: if not keep_tmp: try: shutil.rmtree(tmpdir) except: pass
def _asm(target_arch, target_os, code_blocks, emit_asm = 0, keep_tmp = False): import pwn.internal.shellcode_helper as H import os.path, tempfile, subprocess, string, shutil if target_arch == None: raise Exception('You need to set the architecture with context') tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-') def path(s): return os.path.join(tmpdir, s) try: magic = pwn.randoms(32, only = string.ascii_lowercase) code = [] cpp = ['cpp', '-nostdinc', '-undef', '-w'] if pwn.DEBUG: cpp += ['-D', 'DEBUG'] if target_os != None: include = os.path.join(pwn.installpath, 'pwn', 'include', target_os) cpp += ['-I', include] if target_os == 'linux': if os.path.isfile(os.path.join(include, target_arch + '.h')): cpp += ['-I', os.path.join(include, 'diet')] code += ['#include <%s.h>' % target_arch] elif target_os == 'freebsd': code += ['#include <common.h>'] code += [magic] if target_arch not in ['i386', 'amd64']: code += ['.section .shellcode,"ax"'] asm_extra = [] if target_arch == 'arm': code += ['.arm'] elif target_arch == 'thumb': code += ['.thumb'] target_arch = 'arm' elif target_arch == 'i386': code += ['bits 32'] elif target_arch == 'amd64': code += ['bits 64'] elif target_arch in ['mips', 'mipsel']: code += ['.set mips2'] code += ['.set noreorder'] if target_arch == 'mips': asm_extra += ['--EB'] else: asm_extra += ['--EL'] target_arch = 'mips' code += code_blocks code = '\n'.join(code) if target_arch in ['i386', 'amd64']: assembler = ['nasm', '-Ox'] + asm_extra objcopy = ['objcopy'] else: assembler = [os.path.join(pwn.installpath, 'binutils', target_arch + '-as')] + asm_extra if not os.path.isfile(assembler[0]): raise Exception('Could not find the gnu assembler for this architecture: %s' % target_arch) objcopy = [os.path.join(pwn.installpath, 'binutils', 'promisc-objcopy')] objcopy += ['-j.shellcode', '-Obinary'] if emit_asm == 2: output = [] output += [ "/*", " Assemble with:", " %s [input] -o [input].tmp1" % ' '.join(cpp), " sed -e '0,/^%s$/d' [input].tmp1 > [input].tmp2" % magic, " %s [input].tmp2 -o [input].tmp3" % ' '.join(assembler) ] if target_arch not in ['i386', 'amd64']: output += [" %s [input].tmp3 [output]" % ' '.join(objcopy)] output += ["*/", "", code] return '\n'.join(output) pwn.write(path('step1'), code) _run(cpp + [path('step1'), path('step2')]) code = pwn.read(path('step2')) _code = code.split('\n' + magic + '\n') if len(_code) != 2: raise Exception("The output from cpp was weird:\n%s" % code) code = _code[1] if emit_asm == 1: output = [] if target_arch in ['i386', 'amd64']: output += [ ';; Assemble with:', ';; %s <input> -o <output>' % ' '.join(assembler) ] else: output += [ "/*", " Assemble with:", ' %s <input> -o <input>.tmp' % ' '.join(assembler), ' %s [input].tmp [output]' % ' '.join(objcopy), '*/', ] output += ["", code] return '\n'.join(output) pwn.write(path('step3'), code) _run(assembler + ['-o', path('step4'), path('step3')]) if target_arch in ['i386', 'amd64']: return pwn.read(path('step4')) # Sanity check for seeing if the output has relocations relocs = subprocess.check_output(['readelf', '-r', path('step4')]).strip() if len(relocs.split('\n')) > 1: raise Exception('There were relocations in the shellcode:\n\n%s' % relocs) _run(objcopy + [path('step4'), path('step5')]) return pwn.read(path('step5')) finally: if not keep_tmp: try: shutil.rmtree(tmpdir) except: pass