buuctf——[2019红帽杯]easyRE

64ida
打开后找不到mian函数,看start函数

看伪代码

修改sp值,显示堆栈指针

alt+k对rsi的sp进行修改

改为0x0,得到,就可以看伪代码了

查看字符串
看到这个,查看伪代
signed __int64 sub_4009C6()
{
signed __int64 result; // rax
__int64 v1; // ST10_8
__int64 v2; // ST18_8
__int64 v3; // ST20_8
__int64 v4; // ST28_8
__int64 v5; // ST30_8
__int64 v6; // ST38_8
__int64 v7; // ST40_8
__int64 v8; // ST48_8
__int64 v9; // ST50_8
__int64 v10; // ST58_8
int i; // [rsp+Ch] [rbp-114h]
char v12; // [rsp+60h] [rbp-C0h]
char v13; // [rsp+61h] [rbp-BFh]
char v14; // [rsp+62h] [rbp-BEh]
char v15; // [rsp+63h] [rbp-BDh]
char v16; // [rsp+64h] [rbp-BCh]
char v17; // [rsp+65h] [rbp-BBh]
char v18; // [rsp+66h] [rbp-BAh]
char v19; // [rsp+67h] [rbp-B9h]
char v20; // [rsp+68h] [rbp-B8h]
char v21; // [rsp+69h] [rbp-B7h]
char v22; // [rsp+6Ah] [rbp-B6h]
char v23; // [rsp+6Bh] [rbp-B5h]
char v24; // [rsp+6Ch] [rbp-B4h]
char v25; // [rsp+6Dh] [rbp-B3h]
char v26; // [rsp+6Eh] [rbp-B2h]
char v27; // [rsp+6Fh] [rbp-B1h]
char v28; // [rsp+70h] [rbp-B0h]
char v29; // [rsp+71h] [rbp-AFh]
char v30; // [rsp+72h] [rbp-AEh]
char v31; // [rsp+73h] [rbp-ADh]
char v32; // [rsp+74h] [rbp-ACh]
char v33; // [rsp+75h] [rbp-ABh]
char v34; // [rsp+76h] [rbp-AAh]
char v35; // [rsp+77h] [rbp-A9h]
char v36; // [rsp+78h] [rbp-A8h]
char v37; // [rsp+79h] [rbp-A7h]
char v38; // [rsp+7Ah] [rbp-A6h]
char v39; // [rsp+7Bh] [rbp-A5h]
char v40; // [rsp+7Ch] [rbp-A4h]
char v41; // [rsp+7Dh] [rbp-A3h]
char v42; // [rsp+7Eh] [rbp-A2h]
char v43; // [rsp+7Fh] [rbp-A1h]
char v44; // [rsp+80h] [rbp-A0h]
char v45; // [rsp+81h] [rbp-9Fh]
char v46; // [rsp+82h] [rbp-9Eh]
char v47; // [rsp+83h] [rbp-9Dh]
char v48[32]; // [rsp+90h] [rbp-90h]
int v49; // [rsp+B0h] [rbp-70h]
char v50; // [rsp+B4h] [rbp-6Ch]
char v51; // [rsp+C0h] [rbp-60h]
char v52; // [rsp+E7h] [rbp-39h]
char v53; // [rsp+100h] [rbp-20h]
unsigned __int64 v54; // [rsp+108h] [rbp-18h]
v54 = __readfsqword(0x28u);
v12 = 73;
v13 = 111;
v14 = 100;
v15 = 108;
v16 = 62;
v17 = 81;
v18 = 110;
v19 = 98;
v20 = 40;
v21 = 111;
v22 = 99;
v23 = 121;
v24 = 127;
v25 = 121;
v26 = 46;
v27 = 105;
v28 = 127;
v29 = 100;
v30 = 96;
v31 = 51;
v32 = 119;
v33 = 125;
v34 = 119;
v35 = 101;
v36 = 107;
v37 = 57;
v38 = 123;
v39 = 105;
v40 = 121;
v41 = 61;
v42 = 126;
v43 = 121;
v44 = 76;
v45 = 64;
v46 = 69;
v47 = 67;
memset(v48, 0, sizeof(v48));
v49 = 0;
v50 = 0;
sub_4406E0(0LL, v48, 37LL);
v50 = 0;
if ( sub_424BA0(v48) == 36 )
{
for ( i = 0; i < (unsigned __int64)sub_424BA0(v48); ++i )
{
if ( (unsigned __int8)(v48[i] ^ i) != *(&v12 + i) )// v48[i]^i=v12[i]
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0("continue!");
memset(&v51, 0, 0x40uLL);
v53 = 0;
sub_4406E0(0LL, &v51, 64LL);
v52 = 0;
if ( sub_424BA0(&v51) == 39 )
{
v1 = sub_400E44(&v51);
v2 = sub_400E44(v1);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
if ( !(unsigned int)sub_400360(v10, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v54 )
sub_444020();
return result;
}

v12是初始化过的数组,这里要求要求输入的字符串经过抑或处理等于v12。
写脚本
a=[73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,119,101,107,57,123,105,121,61,126,121,76,64,69,67]
input = ''
for i in range(len(a)):
input += chr(a[i]^i)
print(input)

得到前四个字符是flag

这里是base64加密,加密了10次
解密

一个网址,打开后什么也没有发现。后来才发现下面又调用了sub_400D35函数


第24行v5与一个数组进行了异或,推测得出的是flag。正好验证了之前的结果。可以反向异或得到v5。之后进行第28行的异或得到v2
已知数组:

v5 = ''
enc1 = 'flag'
v2 = ''
enc = [0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
for i in range(4):
v5 += chr(enc[i] ^ ord(enc1[i]))
print (v5)
for i in range(len(enc)):
v2 += chr(enc[i] ^ ord(v5[i%4]))
print(v2)

buuctf Youngter-drive
upx壳,脱壳

双线程,第一个线程h0bject会执行StartAddress函数,第二个线程v2执行。。
第六行函数可以知道Source是我们输入的。第7行CreateMutex的意思是互斥锁。
第九行的StartAddress开始一步步进入

到sub_411940时报错,还是sp值、堆栈的问题。

retn那里为-04,进行修改
堆栈平衡,就可以查看函数sub_411940了

找到了加密函数,这是将字符串进行了替换,当字符是大写字母时,替换为off_418000处-38,小写则替换后-96
它是两个线程同时工作的,要交替数据,这时回过头来看两个线程。


先进行主函数第九行的进程,即使用sub_411940进行加密,然后dword_418008自减一,进程休眠64ms,然后进行主函数第10行的进程,函数dword_418008自减一,进程休眠64ms,然后又是第9行的进程执行。两个进程交替进行,都对dword_418008进行自减一的操作,但是第九行还对Source进行加密操作。

看一下数据

off_418000 = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
off_418004 = "TOiZiZtOrYaToUwPnToBsOaOapsyS"
flag=''
for i in range(len(off_418004)):
if i %2 == 0:
flag += off_418004[i]
continue
for j,k in enumerate(off_418000):
if off_418004[i] == k:
if chr(j+38).isupper():
flag += chr(j+38)
else:
flag += chr(j+96)
print (flag)

提交发现失败,看到了这个

在比对时只比对了29位,所以得出的flag少了一位,所以需要再加一位提交。
flag{ThisisthreadofwindowshahaIsESE}
本文解析了Buuctf Youngter-drive挑战中遇到的加密、壳技术及双线程问题,涉及字符串异或、Base64解密、线程交替加密策略和堆栈修复技巧。核心内容包括找到加密函数、脱壳过程以及最终flag的获取和调整。

2579

被折叠的 条评论
为什么被折叠?



