Jarvis OJ backdoor
这是一个有后门的程序,有个参数可以触发该程序执行后门操作,请找到这个参数,并提交其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虚拟机里面可以,运行了一个计算机
推荐阅读
-
完美解决在oj中Python的循环输入问题
-
OJ上的三道Python题
-
【牛客OJ】输入输出处理
-
『ACM C++』HDU杭电OJ | 1425 - sort (排序函数的特殊应用)
-
『ACM C++』HDU杭电OJ | 1418 - 抱歉 (拓扑学:多面体欧拉定理引申)
-
【LeetCode OJ 328】Odd Even Linked List
-
杭电oj 2734 java实现
-
力扣OJ 剑指 Offer 68 - II. 236. 二叉树的最近公共祖先
-
Backdoor on Pam module pam_unix.so 记录linux root密码
-
『ACM C++』HDU杭电OJ | 1415 - Jugs (灌水定理引申)