Oops-re's Blog.

SYC2022--复现

字数统计: 1.4k阅读时长: 6 min
2022/11/29

[极客大挑战]2022 复现

这次的极客大挑战学到了不少东西,包括之前没有深入了解的

android方面的逆向

RC4加密与解密

Base变表的爆破

pwn方面

主要还是在做题得到角度能到拓展

(做出来的题就不复现了哈)….(@A@)

RE

CrezyThursday.exe

根据官方wp可以知道,这题主要考点就是SMC也就是Self Modifying Code(动态代码加密技术)奇安信攻防社区-初探smc动态代码保护 (butian.net)

==这里我就简单说一下,详细的我另起一篇博客==

这里留给位置贴

主要的流程如下:

1
2
3
4
5
6
IF .运行条件满足  
CALL DecryptProc (Address of MyProc);对某个函数代码解密
........
CALL MyProc ;调用这个函数
........
CALL EncryptProc (Address of MyProc);再对代码进行加密,防止程序被Dump

可以看到这里对一个巨大的数组进行了操作

image-20221129184117213

动调查看操作完以后的函数

发现这里的数据变成PE文件格式

image-20221129184307108

dump下来以后发现这个可能dll文件

image-20221129184513599

和官方wp描述相同,

1
(当时还不知道这题是SMC就动调一直跟进到qword_7FF6D5DDC660...嘿嘿)

继续动调,发现了SMC的第二步,也就是调用解密后的代码,不过这里调用的dll就是了

image-20221129185125134

通过动调拿到调用的dll函数是0x180001000h

回到dll

找到函数

image-20221129185651997

进一步分析

(QAQ我Findcrypt插件分析不出来,不知道是RC4..然后就放弃这题了)

这现在知道了是RC4

这里就贴一个RC4的博客叭(待改)画饼+1

密钥是StartReverse,密文在后面的比对那里

1
E75FC6E9D9E5D6115A85F34934E327DAC8D9BCE153A5F0D5

然后就可以拿到风神那里直接梭哈

image-20221129190904650

拿到flag---SYC{wwww@RC_RC_RC_RC@wwww:)H}

maze

这题我做出来了,迷宫嘛

这里我根据网上的算法写了一个dfs算法找路,但是遍历范围太大了,没遍出来

但是减少他的方向选择就能出来

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
import sys
sys.setrecursionlimit(100000) #例如这里设置为十万

crack = '##########################0#0000000#0#0#000000000##0#######0#0#0#0#0#0###0##00000#000#00000#0#000#0######0###0#0##############0#0#0#0#0#000#0#000#000##0#0#S#0#0#0###0#0###0####000#00000#0#000#000#0#0####0#####0#0#0###0###0#0##0#00000#000#0#0#0#000#0##0#####0#0###0#0#0#0###0##0#000#000#0#0#0#0000000##0###0###0#0#0#0#0#0######0#000000000000000#00000##0#0#######0#####0###0####000#00000000000#000#000######0#####0#########0#0##00000#0000000000000#0#0##0###0#0#0###0###0#####0##000#0#0#0#00000#0#000#0##0#0#0#####0#0#####0######0#0#0#00000#00000000000##0#0#####0#0#0#0#0#####0##0#0#00000#0#0#0#00000#E##########################'
maze = list(crack)
method =['$','&']
path = []
def mark(maze,pos):
maze[pos] = '1'
def find_path(crack,pos,end):
#mark(crack,pos)
if(crack[pos] == 'E'):
print("right!")

return True
for i in method:
if( i == '$'):
npos =pos+ 1
elif(i=='*'):
npos = pos - 1
elif(i=="&"):
npos = pos + 25
if(crack[npos]=='0' or crack[npos]=='E'):
print(i,end='')
if(find_path(crack,npos,end)):
path.append(i)
return True
return False

if __name__ == "__main__":

find_path(maze,155,598)
for i in range(len(path)-1,-1,-1):
print(path[i],end="")

flag–SYC{&$$$$&&&&&&$$&&&&$$&&&&$$$$$$$$$$&&}

EX

C++的异常报错题,比的时候没做好像,最后两天才进的比赛嘛…还要看pwn,孩子看不完哇QAQ。。。

这题看了一天。。真就一天复现一题 ___ 菜Orz(碎碎念)

这题其实是也不是第一次接触C++的异常报错了,不过前几次动调的话还能跑到catch块

但是这题就跑不到….恼…

看了wp学了正常做法

也就是通过patch掉throw,将抛出异常的地方patch成对应的catch块

这里有两种方法…

一种是官方wp的通过动调,trace模块找到对应的throw…catch

image-20221130214550457

另一种就是直接找了

学了一天,发现,catch块都存在相同的函数调用,还挺规范呢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
					   call    ___cxa_begin_catch
.text:000056073D3A1796 mov [rbp+var_88], rax
.text:000056073D3A179D mov eax, cs:dword_56073D3A4010
.text:000056073D3A17A3 mov [rbp+var_A8], eax
.text:000056073D3A17A9 mov eax, cs:dword_56073D3A4014
.text:000056073D3A17AF mov [rbp+var_A4], eax
.text:000056073D3A17B5 mov eax, cs:dword_56073D3A4018
.text:000056073D3A17BB mov [rbp+var_A0], eax
.text:000056073D3A17C1 mov eax, cs:dword_56073D3A401C
.text:000056073D3A17C7 mov [rbp+var_9C], eax
.text:000056073D3A17CD mov eax, cs:dword_56073D3A41D4
.text:000056073D3A17D3 add eax, 1
.text:000056073D3A17D6 mov cs:dword_56073D3A41D4, eax
.text:000056073D3A17DC call ___cxa_end_catch

也就是通过**___cxa_begin_catch___cxa_end_catch**包括catch块

并且IDA也会通过注释的方式,展示catch那里的throw

image-20221130215346078

owned by 地址 就是抛出异常的地方

改它

然后F5出来

(好像没改太对。。。。)

image-20221130215525632这就是改出来的东西,起码能看了。。。是叭

相关的逻辑就是

v24,25分别从后往前进行保存4字节的s(s是输入的字符串)

1
2
v24=s[i];
v25=s[i+4];

(这里进行了两次赋值,所以最后v24=s[8]且v25=s[8+4])

然后有一个key表

image-20221130215808827

在嵌套里面的代码是:

1
2
3
4
for(int k=0;k<=31;k++){
v24 += (v0 + k2) ^ (v0 - k3) ^ roundKey ^ j;
v25 += (v1 + k0) ^ (v1 - k1) ^ roundKey ^ j;
}

官方解题脚本如下图:

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
#include <iostream>
#include <cstdint>
#include <cstdio>
using namespace std;
union solver
{
char flag[17];
uint32_t cipher[4];
};
int main()
{
solver s;
s.cipher[0] = 0xa2216203;
s.cipher[1] = 0xaa9f6a27;
s.cipher[2] = 0x5d411ed3;
s.cipher[3] = 0x503b3f1c;
s.flag[16] = 0;
uint32_t key[4] = {0x11223344, 0x22334455, 0x33445566, 0x44556677};
uint32_t roundKey = 0x99887766;
for(int i = 0; i < 2; i++)
{
uint32_t v0 = s.cipher[i*2], v1 = s.cipher[i*2+1];
uint32_t k0 = key[0], k1 = key[1], k2 = key[2], k3 = key[3];
for(int j = 31; j >=0; j--)
{
v1 -= (v0 + k2) ^ (v0 - k3) ^ roundKey ^ j;
v0 -= (v1 + k0) ^ (v1 - k1) ^ roundKey ^ j;
}
s.cipher[i*2] = v0;
s.cipher[i*2+1] = v1;
}
cout << hex << s.cipher[3] << endl;
string flag = s.flag;
cout << flag << endl;
}


//结果
//3376306c
//syc-w3n-ch4-l0v3

这里使用了unint32_t数据类型,需要配置编译器使用c++11的编译规则

image-20221201191452055

下一题

mvze

虚拟机题目(ezvm)

CATALOG
  1. 1. [极客大挑战]2022 复现
    1. 1.1. RE
      1. 1.1.1. CrezyThursday.exe
      2. 1.1.2. maze
      3. 1.1.3. EX
      4. 1.1.4. mvze