XCTF 进阶 RE The_Maya_Society
这道题目已经困惑我很久了,今天就把他解决了吧,,,,,
首先下载文件有三个,一个网页,一个elf文件,一个文件夹
打开网页没发现什么有用的东西,下载也下载不了,,,,
既然如此,那就直接分析elf文件吧,直接用ida打开,找到主函数:
signed __int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
size_t v3; // rbx
size_t v4; // rax
size_t v6; // rax
size_t v7; // rax
unsigned __int64 v8; // rsi
__int64 v9; // rdi
time_t timer; // [rsp+18h] [rbp-128h]
char v11[8]; // [rsp+20h] [rbp-120h]
char src; // [rsp+40h] [rbp-100h]
char s; // [rsp+60h] [rbp-E0h]
unsigned __int64 v14; // [rsp+C8h] [rbp-78h]
char v15; // [rsp+D4h] [rbp-6Ch]
char v16; // [rsp+DDh] [rbp-63h]
char v17; // [rsp+E6h] [rbp-5Ah]
char v18; // [rsp+EFh] [rbp-51h]
void (__fastcall *v19)(__int64, unsigned __int64); // [rsp+F8h] [rbp-48h]
__int64 v20; // [rsp+100h] [rbp-40h]
char *v21; // [rsp+108h] [rbp-38h]
char *dest; // [rsp+110h] [rbp-30h]
int *v23; // [rsp+118h] [rbp-28h]
size_t v24; // [rsp+120h] [rbp-20h]
struct tm *tp; // [rsp+128h] [rbp-18h]
strcpy(v11, ".fluxfingers.net");
timer = time(0LL);
tp = localtime(&timer);
strftime(&s, 0x63uLL, "%Y-%m-%d", tp);
v24 = strlen(&s);
sub_B5A(&s, v24);
v23 = &dword_2030B8;
snprintf(
&v18,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030B8,
BYTE1(dword_2030B8),
BYTE2(dword_2030B8),
HIBYTE(dword_2030B8));
v23 = &dword_2030C0;
snprintf(
&v17,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030C0,
BYTE1(dword_2030C0),
BYTE2(dword_2030C0),
HIBYTE(dword_2030C0));
v23 = &dword_2030B4;
snprintf(
&v16,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030B4,
BYTE1(dword_2030B4),
BYTE2(dword_2030B4),
HIBYTE(dword_2030B4));
v23 = &dword_2030BC;
snprintf(
&v15,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030BC,
BYTE1(dword_2030BC),
BYTE2(dword_2030BC),
HIBYTE(dword_2030BC));
snprintf(&src, 0x21uLL, "%s%s%s%s", &v18, &v17, &v16, &v15);
v3 = strlen(&src);
v4 = strlen(v11);
dest = (char *)malloc(v3 + v4 + 1);
if ( !dest )
return 1LL;
*dest = 0;
strcat(dest, &src);
strcat(dest, v11);
v21 = (char *)sub_18A4(dest, v11);
if ( !v21 )
return 1LL;
v6 = strlen(v21);
v20 = sub_15E0(v21, v6, &v14);
v7 = strlen(v21);
v19 = (void (__fastcall *)(__int64, unsigned __int64))sub_15E0(v21, v7, &v14);
if ( !v20 )
return 1LL;
v8 = v14;
v9 = v20;
sub_1858(v20, v14, (__int64)v19);
v19(v9, v8);
return 0LL;
}
好像是一个获取本地时间的一个功能,还经过了一个函数的加密:
进入看上去像是MD5加密,,,,,
往后就是一些函数的调用,,,,,
这里是把获取到的时间经过加密,与.fluxfingers.net
连接起来,并且传入到sub_18A4中去
sub_18A4函数如下:
char *__fastcall sub_18A4(const char *a1)
{
char *v2; // rax
ns_rr v3; // [rsp+10h] [rbp-24A0h]
ns_msg v4; // [rsp+430h] [rbp-2080h]
char s; // [rsp+480h] [rbp-2030h]
u_char v6; // [rsp+1480h] [rbp-1030h]
char *dest; // [rsp+2488h] [rbp-28h]
size_t n; // [rsp+2490h] [rbp-20h]
char *v9; // [rsp+2498h] [rbp-18h]
char *src; // [rsp+24A0h] [rbp-10h]
int v11; // [rsp+24ACh] [rbp-4h]
v11 = __res_query(a1, 1, 16, &v6, 4096);
if ( v11 < 0 )
return 0LL;
ns_initparse(&v6, v11, &v4);
v11 = v4._counts[1];
ns_parserr(&v4, ns_s_an, 0, &v3);
ns_sprintrr(&v4, &v3, 0LL, 0LL, &s, 0x1000uLL);
v2 = strchr(&s, 34);
src = v2 + 1;
if ( v2 == (char *)-1LL )
return 0LL;
v9 = strchr(src, 34);
if ( !v9 )
return 0LL;
n = v9 - src;
dest = (char *)malloc(v9 - src + 1);
strncpy(dest, src, n);
dest[n] = 0;
return dest;
}
有几个函数看不懂,,,,
直接查资料,,,,
The res_query() function provides an interface to the server query mecha-
nism. It constructs a query, sends it to the local server, awaits a
response, and makes preliminary checks on the reply. The query requests
information of the specified type and class for the specified fully-qual-
ified domain name dname. The reply message is left in the answer buffer
with length anslen supplied by the caller.
还有ns_initparse、ns_parserr、ns_sprintrr这几个函数,我没找到与之相关的解释,,,,
不过我看见别人的博客里面好像有写,,,大概就是与通信相关的
到这里的意思大概明白了,就是传入本地时间加密后的值连接上.fluxfingers.net
,发送到某个地方去
到这里直接卡死,,,,,
后面借阅了别人的博客,说是什么传入一个正确的时间就会出现flag,,,
这个鬼想的到噢,,,,因为题目中提到了maya,又因为网页下面有一个2012
所以时间就是maya预测的世界末日,简直有毒了~~
直接修改虚拟机时间为2012-12-21,运行程序得到flag:
Reversing.kr Music Player
下载打开,三个文件,阅读readme.txt得到信息:
意思是要播放一分钟以上就能得到flag,这个它限制只能听一分钟
打开直接使用一下,到一分钟的时候出现,,,,:
直接打开OD,查找字符串~
这个地方的1,非常可疑,双击跳转~
直接在这里下个断点:
可以看到59秒的时候直接卡在这里,并且下面还有个弹窗的函数,直接往上找关键的跳转:
找到一个关键的跳转:
jl指令小于就跳转,不小于就往下执行,所以猜是不是每秒钟都会验证
直接修改jl为jmp
显示新的错误,但是我们还能听见歌曲在持续播放,说明大体的思路还是没有问题的~
根据弹窗我们知道,后面肯定还有一个弹窗的位置,具体是何处尚不清楚,直接下断点在jmp的后面(ps:在第59秒的时候下断点,然后直接F8一步一步往下走):
走到此处时出现弹窗:
同理,直接修改jge为jmp,然后运行程序
发现上面出现password字样:
得到flag为:LIstenCare
关于查找第二个窗口位置,还有另外一种方法:
当窗口弹出时,直接F12暂停程序,ALT+K查看堆栈窗口:
然后在堆栈中一直向下翻,找到返回到用户空间,也是能够查看到弹出窗口的位置的: