当前位置: 代码迷 >> 综合 >> Jarvis OJ backdoor
  详细解决方案

Jarvis OJ backdoor

热度:85   发布时间:2023-12-13 04:59:13.0

这是一个有后门的程序,有个参数可以触发该程序执行后门操作,请找到这个参数,并提交其SHA256摘要。(小写)

FLAG:PCTF{参数的sha256}
用这个题来了解一下什么叫后门吧。

signed int __cdecl wmain(int a1, int a2)
{char v3; // [esp+50h] [ebp-2C8h]char v4; // [esp+E1h] [ebp-237h]char v5; // [esp+E4h] [ebp-234h]char Source[4]; // [esp+100h] [ebp-218h]char v7; // [esp+104h] [ebp-214h]__int16 i; // [esp+108h] [ebp-210h]char Dest[2]; // [esp+10Ch] [ebp-20Ch]char Dst; // [esp+10Eh] [ebp-20Ah]char v11[25]; // [esp+110h] [ebp-208h]char v12[483]; // [esp+129h] [ebp-1EFh]__int16 v13; // [esp+30Ch] [ebp-Ch]LPSTR lpMultiByteStr; // [esp+310h] [ebp-8h]int cbMultiByte; // [esp+314h] [ebp-4h]cbMultiByte = WideCharToMultiByte(1u, 0, *(LPCWSTR *)(a2 + 4), -1, 0, 0, 0, 0);lpMultiByteStr = (LPSTR)sub_4011F0(cbMultiByte);WideCharToMultiByte(1u, 0, *(LPCWSTR *)(a2 + 4), -1, lpMultiByteStr, cbMultiByte, 0, 0);v13 = *(_WORD *)lpMultiByteStr;if ( v13 < 0 )return -1;v13 ^= 0x6443u;strcpy(Dest, "0");memset(&Dst, 0, 0x1FEu);for ( i = 0; i < v13; ++i )Dest[i] = 0x41;*(_DWORD *)Source = 0x7FFA4512;v7 = 0;strcpy(&Dest[v13], Source);qmemcpy(&v5, &unk_4021FC, 0x1Au);strcpy(&v11[v13], &v5);qmemcpy(&v3, &unk_402168, 0x91u);v4 = 0;strcpy(&v12[v13], &v3);sub_401000(Dest);return 0;
}

先看看这个程序。命令行参数的第二个传了进来。WideCharToMultiByte(1u, 0, (LPCWSTR )(a2 + 4), -1, lpMultiByteStr, cbMultiByte, 0, 0);这一句把输入命令行第一个参数给了 lpMultiByteStr。后面又传给了v13沿着这条线继续走。v13 =*(_WORD *)lpMultiByteStr;这里穿的是指向的内容,需要注意的是咱们需要的是反着来的,因为v13的定义是__int16 v13。
v13 ^= 0x6443u;进行了一次异或。

for ( i = 0; i < v13; ++i )Dest[i] = 'A';

这里把v13作为数目填充进Dest里面好多‘A’

*(_DWORD *)Source = 0x7FFA4512;v7 = 0;strcpy(&Dest[v13], Source);

这里把0x7FFA4512这个地址传到了Dest[v13]。0x7FFA4512是windows 上一个万能的 jmp esp(几乎所有平台这个地址上都是 jmp esp),然后这个 dest 可以看 ida 上面是 char Dest[2],所以这里可以通过参数控制这个 jmp esp 溢出到某一个函数的返回地址,从而改变程序的控制流去执行此时 esp 上地址的内容。
继续往下sub_401000(Dest);用了Dest

int __cdecl sub_401000(char *Source)
{char Dest[2]; // [esp+4Ch] [ebp-20h]int v3; // [esp+4Eh] [ebp-1Eh]int v4; // [esp+52h] [ebp-1Ah]int v5; // [esp+56h] [ebp-16h]int v6; // [esp+5Ah] [ebp-12h]int v7; // [esp+5Eh] [ebp-Eh]int v8; // [esp+62h] [ebp-Ah]int v9; // [esp+66h] [ebp-6h]__int16 v10; // [esp+6Ah] [ebp-2h]strcpy(Dest, "0");v3 = 0;v4 = 0;v5 = 0;v6 = 0;v7 = 0;v8 = 0;v9 = 0;v10 = 0;strcpy(Dest, Source);return 0;
}

这下清楚了 strcpy(Dest, Source);这里实现了溢出

 char Dest[2]; // [esp+4Ch] [ebp-20h]

需要0x20个字节+4个字节的返回地址也就是说输入的命令行参数处理过之后是0x24字节。这里v13 ^= 0x6443u;处理过一次,所以输入的命令行参数就是chr(0x24^0x43),chr(0x00^0x64)。

import hashlib
flag=""
flag+=chr(0x24^0x43)
flag+=chr(0x00^0x64)print hashlib.sha256(flag).hexdigest()

输出结果

2b88144311832d59ef138600c90be12a821c7cf01a9dc56a925893325c0af99f

总结:
程序给出了返回地址,需要做的是搞清楚程序的逻辑,计算出输入的值多少时刚好能把返回地址覆盖为已给出的地址。

想要pwn 需要:1.有个漏洞让你溢出。2.有个地址来覆盖掉原来的地址。

0x7FFA4512这个地址很有用,windows里面的万能jmp esp。

hash加密:import hashlib
hashlib.sha256(string).hexdigest()

还有一点最有意思的,这个题在win10中调用不了不过在xp虚拟机里面可以,运行了一个计算机
这里写图片描述