0%

d3ctf

D^3CTF

本次CTF终极被虐,太难了,但始终参与进程中,这两天把逆向题复现一下,这次逆向题的”外壳”很难搞定,学到的东西很多,师傅们太强了!

Reverse

D3MUG

这个题是unity3d游戏,而且是一个音游,应该是拿到perfect就会给flag,但被人修改了,用连点器都没用的。

第一次接触unity3d逆向,首先我们要用IL2CPP,来对libil2cpp.soglobal-metadata.dat进行操作

我们先把apk软件解压,找到下述文件,copy到Il2CppDumper.exe的文件夹下。

1
2
\lib\armeabi-v7a\libil2cpp.so`
`\assets\bin\Data\Managed\Metadata\global-metadata.dat

要新建两个文件夹,第一个是input,第二个是output

libil2cpp.soglobal-metadata.dat拷贝到input目录中。再在记事本下输入:

1
..\Il2CppDumper.exe libil2cpp.so global-metadata.dat ..\output

然后重命名成:

1
il2cpp_decompilation.bat

然后运行

发现output文件夹生成

在DummyDll中存在很多dll文件

dump.cs这个文件会把C#dll代码的类、方法、字段列出来

il2cpp.h生成cpp的头文件,从头文件里我们也可以看到相关的数据结构。

script.json以json格式显示类的方法信息:

stringliteral.json以json的格式显示所有的字符串信息:

我们在dump.cs文件中找到ScoreScene类,发现Start会check flag,

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
public class GameManager : MonoBehaviour // TypeDefIndex: 4296
{
// Fields
public static GameManager instance; // 0x0
public TMP_Text GoodText; // 0xC
public TMP_Text PerfectText; // 0x10
public TMP_Text MissText; // 0x14
public BeatScroller beatScroller; // 0x18

// Methods

// RVA: 0x42CD60 Offset: 0x42CD60 VA: 0x42CD60
public static extern void update(uint msecs) { }

// RVA: 0x42CE00 Offset: 0x42CE00 VA: 0x42CE00
private void Start() { }

// RVA: 0x42CF24 Offset: 0x42CF24 VA: 0x42CF24
private void Update() { }

[IteratorStateMachine(typeof(GameManager.<loadBeatmap>d__8))]
// RVA: 0x42CE7C Offset: 0x42CE7C VA: 0x42CE7C
private IEnumerator loadBeatmap() { }

// RVA: 0x42CF50 Offset: 0x42CF50 VA: 0x42CF50
public void NoteHit(float preciseTime, int level) { }

// RVA: 0x42D0A0 Offset: 0x42D0A0 VA: 0x42D0A0
public void NoteMissed() { }

// RVA: 0x42D1B0 Offset: 0x42D1B0 VA: 0x42D1B0
public void .ctor() { }
}

GameManager这个类中的update就是d3mug.so中的update函数

如何恢复libil2cpp.so的字符串和函数:

1.先在ida打开libil2cpp.so文件

2.用Script file打开我们下载文件夹中的ida_with_struct.py脚本

3.然后会直接让选择下一个文件,我们找到output里的文件

4.继续选文件,我们选择il2cpp.h头文件

等待加载就行,但我一加载就卡死,可能这个太大了吧,320mb果然大的离谱

找到score_start函数,卡的要死。。。

在if函数中的就是要检测是否有D3CTF,如果没就会返回这句话,另一个重要的是这个

可知道这个是引用d3mug文件中的update函数

通过对GameManagerupdate进行交叉引用发现是GameManageNoteHit或GameManagerNoteMissed最后调用的GameManagerupdate,对GameManager__NoteHit进行交叉引用就可以得知是从MusicController上获取的时间,如下图

总之,逻辑如下:

玩游戏点击方块后,GameManagerNoteHit之前会从MusicController上获取preciseTime,点击后,GameManagerNoteHit在函数最后调用GameManagerupdate,传入preciseTime,然后update。接下来update检测server::instance,如果没有就初始化,初始化的值不变,若初始化,就再调用d3mug中server::run函数,这个函数会更新instance,最后check的地方也是d3mug中的get文件,拿到最后的instance然后比较是否是D3CTF开头

GameManagerloadBeatmap_d8__MoveNext函数中发现hintpoints很重要

使用AssetstdioGui来载入assets\bin\Data\data.unity3d

搜索hitpoints,发现有3个,通过运行可以得知总共会掉落1608个块,找到了恰好有1608个的hitpoints

1
2
3
4
5
6
7
8
9
10
11
12
13
hitpoints = """4,0 
3,0
1,0
3,146
......
2,140195
1,140195
4,140195
3,140195
"""
arr = []
for l in hitpoints.splitlines():
arr.append(eval(l[l.find(',')+1:]))

提取逗号后面的数,后面的数就是参数

方法一:对函数复原

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
__int64 __fastcall Server::run(__int64 this, char a2)
{
__int64 v2; // x9
__int64 v3; // x8
unsigned __int64 v4; // x13
unsigned __int64 *v5; // x12
unsigned __int64 v6; // x14
unsigned __int64 v7; // x14
__int64 v8; // x14
int *v9; // x12
unsigned __int64 v10; // x8
int v11; // w10
int v12; // w13
int v13; // w15
unsigned __int64 v14; // x8
unsigned __int64 v15; // t2

v2 = *(_QWORD *)(this + 5032);
v3 = this + 40;
v4 = (v2 + 1) % 0x270uLL;
v5 = (unsigned __int64 *)(this + 40 + 8 * v4);
*(_QWORD *)(this + 40 + 8 * v2) = (2567483615u * (*v5 & 1)) ^ *(_QWORD *)(this + 40 + 8 * ((v2 + 397) % 0x270uLL)) ^ ((*v5 & 0x7FFFFFFE | *(_QWORD *)(this + 40 + 8 * v2) & 0xFFFFFFFF80000000LL) >> 1);
v6 = *(_QWORD *)(this + 40 + 8LL * *(_QWORD *)(this + 5032));
*(_QWORD *)(this + 5032) = v4;
v7 = (((unsigned int)(v6 >> 11) ^ (unsigned int)v6) << 7) & 0x9D2C5680 ^ (unsigned int)(v6 >> 11) ^ v6;
if ( (((_DWORD)v7 << 15) & 0xEFC60000 ^ v7 ^ ((((_DWORD)v7 << 15) & 0xEFC60000 ^ v7) >> 18)) % 7 >= 3 )
{
v8 = (unsigned __int16)(v4 + 1) % 0x270u;
*v5 = (2567483615u * (*(_QWORD *)(v3 + 8LL * (unsigned int)v8) & 1LL)) ^ *(_QWORD *)(v3
+ 8LL
* ((unsigned __int16)(v4 + 397)
% 0x270u)) ^ ((*(_QWORD *)(v3 + 8LL * (unsigned int)v8) & 0x7FFFFFFELL | *v5 & 0xFFFFFFFF80000000LL) >> 1);
v9 = (int *)(this + (a2 & 0xF));
v10 = *(_QWORD *)(v3 + 8LL * *(_QWORD *)(this + 5032));
*(_QWORD *)(this + 5032) = v8;
v11 = *v9;
v12 = v9[1];
LODWORD(v8) = v9[2];
v13 = v9[3];
*v9 = v8;
v9[1] = v13;
v14 = (((((unsigned int)(v10 >> 11) ^ (unsigned int)v10) << 7) & 0x9D2C5680 ^ (unsigned int)(v10 >> 11) ^ (unsigned int)v10) << 15) & 0xEFC60000 ^ (((unsigned int)(v10 >> 11) ^ (unsigned int)v10) << 7) & 0x9D2C5680 ^ (unsigned int)(v10 >> 11) ^ v10;
HIDWORD(v15) = v8 ^ (v14 >> 18) ^ v14;
LODWORD(v15) = HIDWORD(v15);
LODWORD(v14) = v15 >> 19;
v9[2] = v14 ^ v11;
v9[3] = v12 ^ __ROR4__(v13, 18) ^ v14;
}
return this;
}

上面是要复原的函数

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
#include <stdio.h>
#include <random>
#include <Windows.h>
using namespace std;

const DWORD hitp[] = { 0,0,0,146,292,292,439,512,585,585,658,731,804,878,1024,1170,1170,1317,1463,1463,1609,1682,1756,1756,1902,2048,2195,2341,2341,2487,2634,2634,2780,2853,2926,2926,3073,3146,3219,3219,3365,3439,3512,3512,3658,3804,3878,3951,4024,4097,4097,4243,4390,4682,4682,4682,4829,4975,4975,5121,5195,5268,5341,5414,5487,5560,5560,5853,5853,5999,6146,6146,6292,6365,6439,6439,6585,6731,6731,6731,7024,7024,7170,7317,7317,7463,7536,7609,7609,7682,7756,7829,7902,7902,7975,8048,8121,8195,8341,8487,8634,8780,9073,9073,9073,9219,9365,9365,9512,9658,9658,9804,9878,9951,9951,10097,10243,10243,10243,10390,10463,10536,10536,10682,10829,10829,10975,11121,11121,11268,11414,11414,11560,11707,11707,11853,11999,11999,11999,12146,12292,12292,12439,12439,12585,12585,12585,12731,12878,12951,13024,13097,13170,13170,13317,13463,13463,13463,13609,13756,13756,13756,13902,14048,14048,14195,14341,14487,14634,14634,14926,14926,14926,15219,15219,15219,15365,15365,15512,15512,15658,15804,15804,15951,16024,16097,16097,16170,16243,16317,16390,16390,16536,16682,16682,16829,16902,16975,16975,17121,17268,17268,17268,17414,17560,17634,17707,17780,17853,17926,17999,18073,18146,18146,18292,18439,18439,18731,18731,18731,18878,19024,19024,19024,19170,19243,19317,19463,19609,19609,19609,19756,19829,19902,20048,20195,20195,20341,20487,20487,20634,20780,20780,20926,21073,21073,21219,21365,21365,21365,21512,21585,21658,21658,21804,21951,21951,21951,22097,22243,22317,22390,22463,22536,22536,22609,22682,22756,22829,22829,22975,23121,23121,23268,23414,23560,23707,23780,23853,23926,23999,23999,24073,24146,24219,24292,24365,24439,24512,24585,24585,24731,24731,24878,24878,24878,25024,25170,25170,25317,25390,25463,25463,25609,25756,25756,25756,25902,25902,26048,26048,26195,26195,26341,26341,26414,26487,26487,26560,26634,26634,26780,26780,26926,27219,27512,27585,27658,27731,27804,27804,28097,28097,28390,28682,28682,28975,29268,29268,29560,29560,29853,29853,30146,30439,30439,30731,31024,31024,31317,31609,31609,31902,32195,32195,32487,32780,32780,32780,33365,33365,33365,33951,33951,34243,34536,34536,34829,35121,35121,35414,35707,35707,35707,35999,36292,36585,36878,36878,37024,37024,37170,37170,37463,37463,37463,37609,37756,37756,37902,38048,38048,38195,38341,38341,38487,38634,38634,38780,38926,39073,39219,39365,39512,39658,39804,39804,39951,40097,40097,40243,40390,40390,40536,40682,40829,40975,40975,41121,41268,41414,41560,41707,41853,41999,42146,42146,42292,42292,42439,42585,42731,42731,42878,42878,43024,43170,43317,43317,43463,43463,43609,43609,43682,43756,43756,43829,43902,43902,44048,44048,44195,44195,44341,44341,44487,44560,44634,44707,44780,44853,44926,44999,45073,45146,45219,45292,45365,45439,45512,45585,45658,45658,45804,45951,45951,46097,46243,46243,46536,46536,46536,46829,46829,46902,46975,47121,47121,47268,47414,47414,47560,47634,47707,47707,47853,47926,47999,47999,48146,48292,48292,48439,48585,48585,48731,48878,48878,49024,49170,49170,49243,49317,49463,49463,49609,49756,49756,49902,49975,50048,50048,50121,50195,50268,50341,50341,50487,50487,50707,50707,50926,50926,51073,51219,51365,51512,51512,51585,51658,51804,51804,51951,52097,52097,52170,52243,52317,52390,52390,52536,52609,52682,52682,52829,52975,52975,53121,53268,53268,53414,53560,53560,53707,53853,53853,53926,53999,54073,54146,54146,54219,54292,54365,54439,54439,54512,54585,54658,54731,54731,54878,54878,55024,55024,55024,55317,55317,55317,55609,55609,55609,55902,55902,55902,56195,56268,56341,56487,56487,56634,56780,56780,56926,56999,57073,57073,57219,57292,57365,57365,57512,57658,57658,57804,57951,57951,58097,58243,58243,58390,58536,58536,58609,58682,58829,58829,58975,59121,59121,59268,59341,59414,59414,59560,59634,59707,59707,59853,59926,59999,59999,60073,60292,60292,60439,60585,60585,60731,60878,60878,60951,61024,61024,61170,61170,61317,61317,61463,61463,61463,61536,61609,61609,61756,61756,61902,61902,62048,62048,62048,62121,62195,62195,62341,62341,62414,62487,62560,62634,62634,62780,62780,62926,62926,63073,63073,63219,63219,63292,63365,63439,63512,63512,63585,63658,63731,63804,63804,63878,63951,64024,64097,64097,64170,64243,64317,64390,64390,64536,64536,64609,64682,64829,64975,65121,65268,65414,65560,65560,65707,65853,65999,66146,66146,66439,66585,66878,67170,67317,67317,67609,67902,68048,68195,68341,68487,68487,68780,68926,69073,69219,69365,69512,69658,69658,69804,69951,70243,70390,70536,70682,70829,70829,71121,71268,71560,71853,71999,71999,72292,72585,72731,72878,73024,73170,73317,73463,73609,73609,73756,73975,74195,74341,74341,74634,74707,74780,74926,74926,75073,75073,75219,75219,75219,75365,75512,75512,75658,75658,75804,75804,75804,75951,76097,76097,76390,76390,76390,76536,76682,76682,76829,76829,76975,76975,76975,77268,77268,77414,77560,77560,77561,77707,77853,77853,77999,77999,78146,78146,78146,78292,78439,78439,78731,78732,78732,78878,79024,79024,79170,79171,79317,79317,79463,79609,79609,79756,79902,79902,80048,80195,80341,80341,80487,80487,80634,80780,80780,80926,80926,81073,81073,81073,81219,81365,81512,81512,81658,81658,81658,81951,81951,81951,82097,82243,82243,82390,82536,82682,82682,82829,82829,82829,82975,83121,83121,83268,83414,83414,83560,83707,83853,83853,83999,83999,83999,84292,84292,84365,84439,84512,84585,84585,84731,84804,84878,84878,84951,85024,85097,85170,85170,85317,85390,85463,85463,85536,85609,85682,85756,85756,85829,85902,85975,86048,86048,86121,86195,86268,86341,86341,86487,86634,86634,86707,86780,86853,86926,86926,87073,87146,87219,87219,87292,87365,87439,87512,87512,87658,87804,87804,87878,87951,88024,88097,88097,88170,88243,88317,88390,88390,88536,88609,88682,88682,88829,88975,88975,89121,89121,89268,89268,89414,89414,89560,89560,89707,89707,89853,89853,89999,89999,90146,90146,90292,90292,90439,90439,90585,90585,90731,90731,90878,90878,91024,91024,91170,91170,91317,91317,91390,91463,91536,91609,91682,91756,91829,91902,91975,92048,92121,92195,92268,92341,92634,92780,92926,93219,93365,93365,93365,93365,93658,93658,93804,93878,93951,93951,94097,94243,94317,94390,94463,94536,94536,94682,94829,94829,94975,95121,95121,95268,95414,95487,95560,95634,95707,95707,95853,95853,95999,95999,96146,96292,96292,96292,96439,96585,96585,96658,96731,96804,96878,96878,97024,97170,97170,97317,97390,97463,97463,97609,97756,97756,97829,97902,98048,98048,98048,98195,98341,98341,98487,98560,98634,98634,98780,98926,98926,99073,99219,99219,99365,99512,99512,99658,99804,99804,99951,100097,100170,100243,100317,100390,100390,100536,100682,100682,100829,100975,100975,100975,101121,101268,101268,101341,101414,101487,101560,101560,101707,101853,101853,101926,101999,102073,102146,102146,102292,102439,102439,102439,102585,102658,102731,102731,102878,103024,103024,103024,103170,103243,103317,103317,103317,103463,103609,103682,103756,103829,103902,103902,104048,104195,104195,104341,104487,104487,104487,104634,104780,104853,104926,104999,105073,105073,105219,105365,105365,105512,105658,105658,105658,105804,105951,105951,106097,106170,106243,106243,106317,106390,106536,106536,106682,106756,106829,106829,106829,106975,107121,107121,107268,107268,107414,107414,107414,107560,107707,107707,107707,107853,107999,107999,107999,108146,108292,108292,108439,108585,108585,108731,108878,108878,108878,109024,109170,109170,109317,109463,109463,109536,109609,109682,109756,109756,109902,110048,110048,110048,110195,110195,110341,110341,110341,110487,110487,110634,110634,110634,110780,110780,110926,110926,110926,111073,111073,111219,111219,111219,111365,111512,111658,111731,111804,111878,111951,112024,112097,112097,112097,112390,112390,112536,112682,112682,112682,112829,112975,112975,113121,113268,113268,113414,113560,113560,113707,113853,113853,113999,114146,114219,114292,114365,114439,114439,114585,114731,114731,114878,115024,115024,115024,115170,115317,115317,115463,115536,115609,115609,115756,115902,115902,115975,116048,116121,116195,116195,116268,116341,116414,116487,116487,116560,116634,116707,116780,116780,116926,117073,117073,117219,117365,117365,117512,117658,117658,117804,117878,117951,117951,118097,118243,118243,118390,118536,118536,118682,118829,118902,118975,119048,119121,119121,119268,119414,119414,119560,119707,119707,119853,119999,119999,120146,120292,120292,120439,120439,120731,121024,121170,121463,121536,121609,121682,121756,121756,121756,121902,122048,122048,122048,122195,122341,122341,122341,122487,122560,122634,122634,122634,122780,122926,122926,122926,123073,123219,123219,123219,123365,123512,123512,123512,123585,123658,123731,123804,123804,123804,123951,124097,124097,124097,124243,124390,124390,124390,124536,124682,124682,124682,124829,124975,124975,124975,125121,125268,125268,125268,125414,125487,125560,125560,125560,125707,125853,125853,125853,125999,126146,126146,126146,126292,126439,126439,126439,126585,126585,126731,126731,126878,126878,127024,127024,127024,127170,127170,127317,127317,127463,127463,127609,127609,127609,127756,127756,127902,127902,128048,128048,128195,128195,128268,128341,128341,128414,128487,128487,128560,128634,128707,128780,128780,128853,128926,128999,129073,129146,129219,129292,129365,129365,129439,129512,129585,129658,129731,129804,129878,129951,129951,130024,130097,130170,130243,130243,130317,130390,130463,130536,130536,130682,130756,130829,130829,130829,130975,130975,131121,131195,131268,131341,131560,131707,131707,131780,131853,131926,132146,132292,132365,132439,132512,132731,132878,132878,132951,133024,133097,133463,133463,133756,134048,134048,134048,134341,134634,134634,134926,134926,135219,135219,135219,135512,135512,135658,135658,135804,135804,135951,135951,136097,136097,136243,136243,136390,136390,136536,136536,136609,136682,136682,136829,136829,136902,136975,136975,137121,137121,137268,137268,137414,137414,137560,137560,137707,137707,137780,137853,137926,137999,137999,138073,138146,138146,138219,138292,138365,138439,138439,138512,138585,138658,138731,138731,138804,138878,138951,139024,139024,139097,139170,139243,139317,139317,139463,139463,139609,139609,139756,139756,139902,139902,140195,140195,140195,140195 };

DWORD __ROR4__(DWORD a1, char a2)
{
return (a1 >> a2) | (a1 << (32 - a2));
}



int rounds(uint8_t* bytes, unsigned int a2, int a3)
{
DWORD* v3; // r4
DWORD v4; // r12
DWORD v5[2]; // r5
DWORD v6; // r3
DWORD result; // r0

v3 = (DWORD*)((char*)bytes + a3);
v4 = *(DWORD*)((char*)bytes + a3);
*(DWORD64*)&v5[0] = *(DWORD64*)((char*)bytes + a3 + 4);
v6 = *(DWORD*)((char*)bytes + a3 + 12);
*(DWORD*)((char*)bytes + a3) = *(&v5[0] + 1);
result = v4 ^ __ROR4__(*(&v5[0] + 1) ^ a2, 19);
v3[3] = v5[0] ^ __ROR4__(v6, 18) ^ __ROR4__(*(&v5[0] + 1) ^ a2, 19);
v3[1] = v6;
v3[2] = result;
return result;
}



int main(int argc, char const* argv[])
{
unsigned char enc_bytes[] =
{
0x3C, 0xAC, 0x92, 0x6F, 0x44, 0xA1, 0xC1, 0x17, 0xFD, 0x62,
0x60, 0xDD, 0x63, 0xF8, 0xE3, 0x2A, 0x5E, 0x75, 0x78, 0xBE,
0x59, 0x46, 0x33, 0xF6, 0x2E, 0x64, 0x61, 0x8A, 0x27, 0x93,
0x21, 0x7D, 0x00
};
mt19937 rng(-196167794);
for (int i = 0; i < 1608; ++i)
{
if (rng() % 7 >= 3)
{
rounds(enc_bytes, rng(), hitp[i] & 0xF);
}
}
printf("%s\n", enc_bytes);
getchar();
return 0;
}
//D3CTF{Gb78e-7b04-4364-82d2-7f44}

我只能说写出这个脚本的人是神!

方法二:用frida

frida hook得到最后的server::instance,也就是flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function hooktest () { 
let i = 0;
var d3mug = Module.findBaseAddress("libd3mug.so");
Interceptor.attach(d3mug.add(0x0000780), {
onEnter: function (args) {
var real_time = arr[i++];
args[0] = new NativePointer(real_time);
},
onLeave: function (arg) {
console.log(hexdump(d3mug.add(0x0000000000002D18).readPointer()));
return arg;
}
});
}
setImmediate(function () {
setTimeout(hooktest, 100);
})

安卓机子到了再搞。

d3arm

这个题也是第一次见,给了一个bin文件,首先我们将bin转换成hex文件,然后用ida的arm小端来打开hex文件就行

上面是主函数

这个函数选择难度,我们必须选择hard难度 这样这个MEMORY[0x200028E4] == 450000才成立

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int sub_5FA4()
{
sub_75C2(536880148);
sub_765E(536880148, 536871392, 6);
sub_75D0(536880148, (const char *)&unk_6068);
sub_75D0(536880148, " You get %2d points ", MEMORY[0x2000326C]);
sub_75D0(536880148, " Good! Try it again. ");
sub_75D0(536880148, " ");
sub_7610(536880148);
if ( MEMORY[0x2000326C] == 42 && MEMORY[0x200028E4] == 450000 )
{
sub_75C2(536880148);
sub_765E(536880148, 536871392, 6);
sub_75D0(536880148, (const char *)0x800E094);
sub_75D0(536880148, " flag is shown below ");
sub_75D0(536880148, (const char *)0x200022C8);
sub_7610(536880148);
}
return sub_7F48(1000000);
}

我们通过字符串找到主函数

我们发现对比是内存中*(0x2000326C)== 42 *(0x200028E4)== 45000

这个是对flag的生成

通过对异或的值交叉引用发现异或的值有一个生成过程

找到异或后的值的生成位置

直接写脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xor_arr = [] 
for i in range(42):
v1 = i % 3
xor_arr.append((0x335E44 >> (8 * v1)) & 0xff)
cmp = [0x00000020, 0x0000006D, 0x00000050, 0x00000030, 0x00000038, 0x00000048,
0x00000020, 0x0000006C, 0x00000007, 0x0000007D, 0x0000006C, 0x00000055,
0x0000007D, 0x00000068, 0x00000003, 0x00000027, 0x00000066, 0x00000000,
0x00000022, 0x00000069, 0x00000002, 0x0000007D, 0x0000006D, 0x0000000B,
0x00000077, 0x0000003B, 0x00000002, 0x00000027, 0x0000003B, 0x00000050,
0x00000073, 0x00000038, 0x00000004, 0x00000071, 0x0000003B, 0x00000050,
0x0000007D, 0x0000006A, 0x00000052, 0x00000075, 0x0000006D, 0x0000004E]
for j in range(len(cmp)):
print(chr(cmp[j] ^ xor_arr[j]), end='')
# d3ctf{d2492f960c83f719383e1cec7f75ec94a13}

d3thon

第一次见这种题,给了三种文件,从未见过lbc文件,剩下也不知道是做什么用的,师傅们说是pyd文件,然后可以用python3.1跑起来,lbc包含了指令的逻辑,so文件是类似解释器的东西

这个lbc文件可用010打开

那只能硬猜是什么意思了,在一些函数中添加输出,发现start中循环16次,所以我们能猜测出

FLNPsiCIvICFtzpUAR:cnt1:1表示cnt +=1,那么FLNPsiCIvICFtzpUAR代表add

OuGFUKNGxNLeHOudCK:cnt1:0:1表示cnt1>0时准备jmp到下面的函数

ZOAmcoLkGlAXXqf就是定义函数吧

1
2
3
4
5
6
7
8
9
10
kZslMZYnvPBwgdCz print 
oGwDokoxZgoeViFcAF 赋值(如果赋值为KezJKhCxGRZnfLCGT, 则为输入
RDDDZUiIKbxCubJEN jmp
todeVDuRkYSIITaT 转为2进制
uPapnsSbmeJLjin 转为10进制
kuhisCvwaXWfqCs -flag - 1
IEKMEDdrPpzpdKy add
OcKUQCYqhwHXfAgGZH xor
FLNPsiCIvICFtzpUAR sub
OuGFUKNGxNLeHOudCK cmp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fp = open('data.txt','r')
a = fp.read().strip().replace("'",'').split('\n')
fpout = open('data2.txt','w')
out_list = []
a = a[::-1]

for l in a:
l = l.split(':')
if l[0] =='kuhisCvwaXWfqCs':
fpout.write('flag = -flag\n')
elif l[0] == 'IEKMEDdrPpzpdKy':
fpout.write('flag -= ' + l[2] + '\n')
elif l[0] == 'FLNPsiCIvICFtzpUAR':
fpout.write('flag += ' + l[2] + '\n')
elif l[0] == 'OcKUQCYqhwHXfAgGZH':
fpout.write('flag ^= ' + l[2] + '\n')

我们可以按上面的逻辑进行字符串的替换,得到一个新的脚本,这个脚本就是完全逆向的。

整理输出flag

d3hotel

这个题哦其实没那么麻烦,我们在网站中点f12查看文件,这个网页上总共四个文件

这有3个还有数据包在url中

拿到数据包就导入assertstdiogui查看

其中main.lua是重点,我们取下来,然后进行反编译

如何进行lua的反编译,首先将lua文件和unluac.jar文件放在一个文件夹中

1
java -jar unlua.jar main.lua>main1.lua

main1.lua就是我们要的反编译后的程序

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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
local L0_1, L1_1, L2_1, L3_1, L4_1, L5_1, L6_1, L7_1, L8_1, L9_1, L10_1, L11_1
L0_1 = require
L1_1 = "matrix"
L0_1 = L0_1(L1_1)
matrix = L0_1
L0_1 = matrix
L1_1 = 5
L2_1 = 5
L3_1 = 0
L0_1 = L0_1(L1_1, L2_1, L3_1)
m = L0_1
L0_1 = matrix
L1_1 = {}
L2_1 = {}
L3_1 = 6422944
L4_1 = -7719232
L5_1 = 41640292
L6_1 = -1428488
L7_1 = -36954388
L2_1[1] = L3_1
L2_1[2] = L4_1
L2_1[3] = L5_1
L2_1[4] = L6_1
L2_1[5] = L7_1
L3_1 = {}
L4_1 = 43676120
L5_1 = -26534136
L6_1 = -31608964
L7_1 = -20570796
L8_1 = 22753040
L3_1[1] = L4_1
L3_1[2] = L5_1
L3_1[3] = L6_1
L3_1[4] = L7_1
L3_1[5] = L8_1
L4_1 = {}
L5_1 = -6066184
L6_1 = 30440152
L7_1 = 5229916
L8_1 = -16857572
L9_1 = -16335464
L4_1[1] = L5_1
L4_1[2] = L6_1
L4_1[3] = L7_1
L4_1[4] = L8_1
L4_1[5] = L9_1
L5_1 = {}
L6_1 = -8185648
L7_1 = -17254720
L8_1 = -22800152
L9_1 = -8484728
L10_1 = 44642816
L5_1[1] = L6_1
L5_1[2] = L7_1
L5_1[3] = L8_1
L5_1[4] = L9_1
L5_1[5] = L10_1
L6_1 = {}
L7_1 = -35858512
L8_1 = 10913104
L9_1 = -4165844
L10_1 = 37696936
L11_1 = -10061980
L6_1[1] = L7_1
L6_1[2] = L8_1
L6_1[3] = L9_1
L6_1[4] = L10_1
L6_1[5] = L11_1
L1_1[1] = L2_1
L1_1[2] = L3_1
L1_1[3] = L4_1
L1_1[4] = L5_1
L1_1[5] = L6_1
L0_1 = L0_1(L1_1)
n = L0_1
function L0_1(A0_2)
local L1_2, L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2
L1_2 = #A0_2
if L1_2 ~= 25 then//矩阵长度25
L1_2 = 0
return L1_2
end
L1_2 = 1
L2_2 = 5
L3_2 = 1
for L4_2 = L1_2, L2_2, L3_2 do
L5_2 = 1
L6_2 = 5
L7_2 = 1
for L8_2 = L5_2, L6_2, L7_2 do
L9_2 = m
L9_2 = L9_2[L4_2]
L10_2 = string
L10_2 = L10_2.byte
L11_2 = A0_2
L12_2 = L4_2 - 1
L12_2 = L12_2 * 5
L12_2 = L12_2 + L8_2
L10_2 = L10_2(L11_2, L12_2)
L9_2[L8_2] = L10_2
end
end
L1_2 = tonumber
L2_2 = string
L2_2 = L2_2.format
L3_2 = "%.5f"
L4_2 = matrix
L4_2 = L4_2.det
L5_2 = m
L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2 = L4_2(L5_2)
L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2 = L2_2(L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2)
L1_2 = L1_2(L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2)
det = L1_2
L1_2 = matrix
L2_2 = 5
L3_2 = "I"
L1_2 = L1_2(L2_2, L3_2)
L2_2 = det
L1_2 = L1_2 * L2_2
L2_2 = m
L3_2 = n
L2_2 = L2_2 * L3_2
if L1_2 == L2_2 then//matrix(5, "I") * tonumber(L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2) == m * n
L1_2 = 1
L1_2 = 1
return L1_2
else
L1_2 = 0
return L1_2
end
end
f = L0_1

https://github.com/davidm/lua-matrix/blob/master/lua/matrix.lua源码

我们可以推出单位矩阵xdet(m)== nm

所以只需要求m就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np 
det_n = np.linalg.det(n)
sq2 = np.sqrt(det_n)
sq4 = np.sqrt(sq2)
m = n.I * sq4
print(m)
[[-100. -51. -99. -116. -102.]
[-123. -87. -51. -98. -97.]
[ -53. -109. -95. -49. -115.]
[ -95. -65. -119. -101. -53.]
[-111. -111. -109. -51. -125.]]
m = [[-100, -51, -99, -116, -102],
[-123, -87, -51, -98, -97],
[ -53, -109, -95, -49, -115],
[ -95, -65, -119, -101, -53],
[-111, -111, -109, -51, -125]]
for l in m:
for x in l:
print(chr(-x),end='')
d3ctf{W3ba5m_1s_Awe5oom3}

交上去不对,然后找了许多地方,找到验证处

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
void unnamed_function_39846(int param1,undefined4 param2)

{
int iVar1;
undefined4 uVar2;
int param1_00;
int param2_00;
undefined4 *puVar3;

if (cRam002f65f4 == '\0') {
unnamed_function_432(0x24b40c);
unnamed_function_432(0x24b8dc);
unnamed_function_432(0x252bd4);
unnamed_function_432(0x251d78);
unnamed_function_432(0x24fac4);
cRam002f65f4 = '\x01';
}
iVar1 = unnamed_function_1598
(*(undefined4 *)(*(int *)(param1 + 0xc) + 0xc),uRam00252bd4,uRam0024b8dc);
uVar2 = unnamed_function_670(param1,0);
param1_00 = unnamed_function_702(uVar2,uRam0024b40c);
param2_00 = unnamed_function_4566(*(undefined4 *)(param1_00 + 0x110),0);
if (*(int *)(param2_00 + 0xc) == 0x19) { //长度比较
*(short *)(param2_00 + 0x22) = *(short *)(param2_00 + 0x22) + 0x21;
//这里对输入的某个字符进行了+0x21的操作
}
uVar2 = unnamed_function_4565(0,param2_00,0);
puVar3 = (undefined4 *)0x24fac4;
iVar1 = (**(code **)((longlong)*(int *)(iVar1 + 0xc) * 8))
(*(undefined4 *)(iVar1 + 0x20),uVar2,*(undefined4 *)(iVar1 + 0x14));
if (iVar1 != 1) { //1
puVar3 = (undefined4 *)0x251d78;
}
unnamed_function_6086(param1_00,*puVar3,0);
return;
}

也就是说我们在验证长度后,又对某个字符进行+33的操作,那么直接爆破试试就行了!

d3ctf{W3b@5m_1s_Awe5oom3}

d3wow

这个题是一道迷宫题,给了两个函数,第一个函数是要求输入1,2,3,4但都不能超范围,通过动调发现这个函数还在验证前几个字符是否是d3ctf{2,

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
int __cdecl sub_401000(int a1, int a2)
{
int v3; // [esp+0h] [ebp-10h]
int v4; // [esp+8h] [ebp-8h]
int v5; // [esp+Ch] [ebp-4h]

v5 = 0;
v4 = 0;
v3 = 6;
if ( *(_DWORD *)a1 != 1952658276 )
return 1;
if ( *(_WORD *)(a1 + 4) != 31590 )
return 1;
if ( *(_BYTE *)(a1 + 6) != 50 )
return 1;
while ( *(_BYTE *)(v3 + a1) != 125 )
{
switch ( *(_BYTE *)(v3 + a1) )
{
case '1':
*(_DWORD *)(a2 + 24 * v5 + 4 * v4) |= 8u;
*(_DWORD *)(a2 + 24 * --v5 + 4 * v4) |= 2u;
goto LABEL_14;
case '2':
*(_DWORD *)(a2 + 24 * v5 + 4 * v4) |= 2u;
*(_DWORD *)(a2 + 24 * ++v5 + 4 * v4) |= 8u;
goto LABEL_14;
case '3':
*(_DWORD *)(a2 + 24 * v5 + 4 * v4) |= 4u;
*(_DWORD *)(a2 + 24 * v5 + 4 * v4-- - 4) |= 1u;
goto LABEL_14;
case '4':
*(_DWORD *)(a2 + 24 * v5 + 4 * v4) |= 1u;
*(_DWORD *)(a2 + 24 * v5 + 4 * v4++ + 4) |= 4u;
LABEL_14:
if ( v5 < 0 || v4 < 0 || v5 > 5 || v4 > 5 )
return 1;
++v3;
break;
default:
return 1;
}
}
return 0;
}

这个函数很好理解,下一个函数明显是64位的,但被嵌在32位中了,我们通过dump进行提取:

在32位里打开找到函数地址

dump出来再用64 位打开,进行创建函数

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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
int64 sub_0()
{
_DWORD *v0; // rcx
int v2; // [rsp+0h] [rbp-A8h]
int v3; // [rsp+0h] [rbp-A8h]
int v4; // [rsp+0h] [rbp-A8h]
int v5; // [rsp+4h] [rbp-A4h]
int v6; // [rsp+4h] [rbp-A4h]
int v7; // [rsp+4h] [rbp-A4h]
int i; // [rsp+8h] [rbp-A0h]
int j; // [rsp+Ch] [rbp-9Ch]
int v10; // [rsp+10h] [rbp-98h]
int v11; // [rsp+14h] [rbp-94h]
int k; // [rsp+18h] [rbp-90h]
int m; // [rsp+1Ch] [rbp-8Ch]
unsigned int v14; // [rsp+20h] [rbp-88h]
unsigned int v15; // [rsp+24h] [rbp-84h]
unsigned int v16; // [rsp+28h] [rbp-80h]
unsigned int v17; // [rsp+2Ch] [rbp-7Ch]
unsigned int v18; // [rsp+30h] [rbp-78h]
unsigned int v19; // [rsp+34h] [rbp-74h]
int v20[4]; // [rsp+38h] [rbp-70h]
int v21[10]; // [rsp+48h] [rbp-60h]
__int64 v22; // [rsp+70h] [rbp-38h]
__int64 v23; // [rsp+78h] [rbp-30h]
__int64 v24; // [rsp+80h] [rbp-28h]
__int64 v25; // [rsp+88h] [rbp-20h]
__int64 v26; // [rsp+90h] [rbp-18h]
__int64 v27; // [rsp+98h] [rbp-10h]
_DWORD *retaddr; // [rsp+B0h] [rbp+8h]

MEMORY[0x12F0]((unsigned int)retaddr);
retaddr = v0;
v20[0] = 0;
v20[1] = 14;
v20[2] = 20;
v21[0] = 4;
v21[1] = 13;
v21[2] = 15;
v21[3] = 21;
v21[4] = 24;
v21[5] = 31;
v21[6] = 32;
v21[7] = 41;
v21[8] = 45;
v21[9] = 53;
for ( i = 0; i < 6; ++i )
{
for ( j = 0; j < 6; ++j )
{
if ( retaddr[6 * i + j] > 0xFu )
return MEMORY[0x1301]();
v14 = retaddr[6 * i + j] % 0x10u / 8;//得到的结果是0,1
v22 = j;
v15 = retaddr[6 * i + j] % 8u / 4 + v14;
v23 = j;
v16 = retaddr[6 * i + j] % 4u / 2 + v15;//这个加起来最大是4,代表4条路
v24 = j;
if ( retaddr[6 * i + j] % 2u + v16 > 2 || !j && retaddr[6 * i] % 8u / 4 )//前面代表路径不能超过2
return MEMORY[0x1301]();
if ( j == 5 && retaddr[6 * i + 5] % 2u || !i && retaddr[j] % 0x10u / 8 || i == 5 && retaddr[j + 30] % 4u / 2 )//能推出1,3是下或者2,3是右,直接猜出上下左右是3142
return MEMORY[0x1301]();//上述是检测是否到达边界
}
}
//特殊点1
for ( k = 0; (unsigned __int64)k < 3; ++k )
{
v2 = v20[k] / 10;//分别是0,1,2,代表列
v5 = v20[k] % 10;//分别是0,4,0,代表行
//平行的方向不能同时出现,也就是方向必须垂直
if ( retaddr[6 * v2 + v5] % 0x10u / 8 && retaddr[6 * v2 + v5] % 4u / 2 )
return MEMORY[0x1301]();
if ( retaddr[6 * v2 + v5] % 8u / 4 && retaddr[6 * v2 + v5] % 2u )
return MEMORY[0x1301]();
v17 = retaddr[6 * v2 + v5] % 0x10u / 8;
v25 = v5;
v18 = retaddr[6 * v2 + v5] % 4u / 2 + v17;
v26 = v5;
v19 = retaddr[6 * v2 + v5] % 2u + v18;
v27 = v5;
if ( retaddr[6 * v2 + v5] % 8u / 4 + v19 != 2 )//该点通道必须等于2
return MEMORY[0x1301]();
//下个点与该点方向相同
if ( retaddr[6 * v2 + v5] % 0x10u / 8 )
{
if ( !(retaddr[6 * v2 - 6 + v5] % 0x10u / 8) )
return MEMORY[0x1301]();
}
else if ( retaddr[6 * v2 + v5] % 4u / 2 )
{
if ( !(retaddr[6 * v2 + 6 + v5] % 4u / 2) )
return MEMORY[0x1301]();
}
else if ( retaddr[6 * v2 + v5] % 8u / 4 )
{
if ( !(retaddr[6 * v2 - 1 + v5] % 8u / 4) )
return MEMORY[0x1301]();
}
else if ( retaddr[6 * v2 + v5] % 2u && !(retaddr[6 * v2 + 1 + v5] % 2u) )
{
return MEMORY[0x1301]();
}
}
//特殊点2
for ( m = 0; (unsigned __int64)m < 0xA; ++m )
{
v3 = v21[m] / 10;//0,1,1,2,2,3,3,4,4,5列
v6 = v21[m] % 10;//4,3,5,1,4,1,2,1,5,3行
//方向平行
if ( (!(retaddr[6 * v3 + v6] % 0x10u / 8) || !(retaddr[6 * v3 + v6] % 4u / 2))
&& (!(retaddr[6 * v3 + v6] % 8u / 4) || !(retaddr[6 * v3 + v6] % 2u))
|| retaddr[6 * v3 + v6] % 0x10u / 8//必须有垂直该点的通道
&& retaddr[6 * v3 + v6] % 4u / 2
&& !(retaddr[6 * v3 - 6 + v6] % 8u / 4)
&& !(retaddr[6 * v3 - 6 + v6] % 2u)
&& !(retaddr[6 * v3 + 6 + v6] % 8u / 4)
&& !(retaddr[6 * v3 + 6 + v6] % 2u)
|| retaddr[6 * v3 + v6] % 8u / 4
&& retaddr[6 * v3 + v6] % 2u
&& !(retaddr[6 * v3 + 1 + v6] % 0x10u / 8)
&& !(retaddr[6 * v3 + 1 + v6] % 4u / 2)
&& !(retaddr[6 * v3 - 1 + v6] % 0x10u / 8)
&& !(retaddr[6 * v3 - 1 + v6] % 4u / 2) )
{
return MEMORY[0x1301]();
}
}
v10 = 0;
v11 = 0;
v4 = 0;
v7 = 0;
//自动寻路
if ( *retaddr % 0x10u / 8 )
{
v4 = -1;
while ( 1 )
{
LABEL_67:
if ( !(retaddr[6 * v4 + v7] % 0x10u / 8) || v4 - 1 == v10 && v7 == v11 )
{
if ( !(retaddr[6 * v4 + v7] % 4u / 2) || v4 + 1 == v10 && v7 == v11 )
{
if ( !(retaddr[6 * v4 + v7] % 8u / 4) || v4 == v10 && v7 - 1 == v11 )
{
if ( !(retaddr[6 * v4 + v7] % 2u) || v4 == v10 && v7 + 1 == v11 )
return MEMORY[0x1301]();
v10 = v4;
v11 = v7++;
}
else
{
v10 = v4;
v11 = v7--;
}
}
else
{
v10 = v4;
v11 = v7;
++v4;
}
}
else
{
v10 = v4;
v11 = v7;
--v4;
}
if ( !v4 && !v7 )
return MEMORY[0x1301]();
}
}
if ( *retaddr % 4u / 2 )
{
v4 = 1;
goto LABEL_67;
}
if ( *retaddr % 8u / 4 )
{
v7 = -1;
goto LABEL_67;
}
if ( *retaddr % 2u )
{
v7 = 1;
goto LABEL_67;
}
return MEMORY[0x1301]();
}

得到图:

实心图是特殊点1,空心是特殊点2,左上角出发!

d3ctf{22441442223133324424441111133333}

Misc

BadW3ter

image-20220314141125696

改一下image-20220314141139098

猜想CUY1nw31lai为deepsound的密码,然后解出一个图片,但图片是tif文件,我们用ps打开,发现该图片是叠加的

image-20220314141343566

我们使用油漆桶吧背景搞黑,二维码就变了

image-20220314141319681

D3CTF{M1r@9e_T@nK_1s_Om0sh1roiii1111!!!!!Isn’t_1t?}