欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Jarvis OJ backdoor

程序员文章站 2022-05-16 09:11:30
...

这是一个有后门的程序,有个参数可以触发该程序执行后门操作,请找到这个参数,并提交其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虚拟机里面可以,运行了一个计算机
Jarvis OJ backdoor