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虚拟机里面可以,运行了一个计算机
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_38204481/article/details/79870305