buu [SWPU2019]ReverseMe1 wp

用exeinfo打开,发现是32位的程序。

直接用ida打开看看:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // ecx
  int *v4; // eax
  int v5; // ecx
  int *v6; // eax
  char *v7; // esi
  signed int v8; // edi
  unsigned int v9; // kr00_4
  _BYTE *v10; // ecx
  _QWORD *v11; // ecx
  int *v12; // ecx
  __int128 *v13; // edx
  unsigned int v14; // edi
  int v15; // eax
  int v16; // eax
  bool v17; // cf
  unsigned __int8 v18; // al
  unsigned __int8 v19; // al
  unsigned __int8 v20; // al
  const char *v21; // edx
  int *v22; // eax
  char *v23; // eax
  void *v25; // [esp+24h] [ebp-A0h]
  int v26; // [esp+34h] [ebp-90h]
  unsigned int v27; // [esp+38h] [ebp-8Ch]
  __int128 v28; // [esp+3Ch] [ebp-88h]
  __int128 v29; // [esp+4Ch] [ebp-78h]
  int v30; // [esp+5Ch] [ebp-68h]
  __int128 v31; // [esp+60h] [ebp-64h]
  __int128 v32; // [esp+70h] [ebp-54h]
  int v33; // [esp+80h] [ebp-44h]
  __int64 v34; // [esp+84h] [ebp-40h]
  int v35; // [esp+8Ch] [ebp-38h]
  __int16 v36; // [esp+90h] [ebp-34h]
  int v37; // [esp+94h] [ebp-30h]
  int v38; // [esp+98h] [ebp-2Ch]
  int v39; // [esp+9Ch] [ebp-28h]
  int v40; // [esp+A0h] [ebp-24h]
  int v41; // [esp+A4h] [ebp-20h]
  int v42; // [esp+A8h] [ebp-1Ch]
  int v43; // [esp+ACh] [ebp-18h]
  int v44; // [esp+B0h] [ebp-14h]
  int v45; // [esp+C0h] [ebp-4h]

  v26 = 0;
  v27 = 15;
  LOBYTE(v25) = 0;
  v45 = 0;
  LOBYTE(v45) = 1;
  v4 = printff(v3, "Please input your flag: ");
  sub_403050((int)v4);
  scanf(&dword_430068, &v25);
  v35 = 1413701433;
  v34 = qword_42B9A0;
  v36 = 70;
  if ( v26 == 32 )
  {
    v41 = -1173078761;
    v42 = 494076752;
    v43 = -1811652486;
    v44 = 688582768;
    v8 = 0;
    v31 = 0i64;
    v33 = 0;
    v32 = 0i64;
    v9 = strlen((const char *)&v34);
    do
    {
      v10 = &v25;
      if ( v27 >= 0x10 )
        v10 = v25;
      v10[v8] ^= *((_BYTE *)&v34 + v8 % v9);
      ++v8;
    }
    while ( v8 < 32 );
    v11 = &v25;
    v7 = (char *)v25;
    if ( v27 >= 0x10 )
      v11 = v25;
    v30 = 0;
    v28 = 0i64;
    v29 = 0i64;
    *(_QWORD *)&v31 = *v11;
    *((_QWORD *)&v31 + 1) = v11[1];
    *(_QWORD *)&v32 = v11[2];
    *((_QWORD *)&v32 + 1) = v11[3];
    sub_4025C0();
    v37 = -133220429;
    v38 = 1571732668;
    v12 = &v37;
    v39 = -2041750854;
    v13 = &v28;
    v40 = -748513468;
    v14 = 28;
    v41 = 371505743;
    v42 = 443719435;
    v43 = 644704357;
    v44 = 1741188026;
    while ( 1 )
    {
      v15 = *v12;
      if ( *v12 != *(_DWORD *)v13 )
        break;
      ++v12;
      v13 = (__int128 *)((char *)v13 + 4);
      v17 = v14 < 4;
      v14 -= 4;
      if ( v17 )
      {
        v16 = 0;
        goto LABEL_19;
      }
    }
    v17 = (unsigned __int8)v15 < *(_BYTE *)v13;
    if ( (_BYTE)v15 != *(_BYTE *)v13
      || (v18 = *((_BYTE *)v12 + 1), v17 = v18 < *((_BYTE *)v13 + 1), v18 != *((_BYTE *)v13 + 1))
      || (v19 = *((_BYTE *)v12 + 2), v17 = v19 < *((_BYTE *)v13 + 2), v19 != *((_BYTE *)v13 + 2))
      || (v20 = *((_BYTE *)v12 + 3), v17 = v20 < *((_BYTE *)v13 + 3), v20 != *((_BYTE *)v13 + 3)) )
    {
      v16 = -v17 | 1;
    }
    else
    {
      v16 = 0;
    }
LABEL_19:
    if ( v16 )
      v21 = "Try again!\r\n";
    else
      v21 = "Congratulations! I always knew you could do it.";
    v22 = printff((int)v12, v21);
    sub_403050((int)v22);
    sub_40ADBE("pause");
  }
  else
  {
    v6 = printff(v5, "Try again!\r\n");
    sub_403050((int)v6);
    sub_40ADBE("pause");
    v7 = (char *)v25;
  }
  if ( v27 >= 0x10 )
  {
    v23 = v7;
    if ( v27 + 1 >= 0x1000 )
    {
      v7 = (char *)*((_DWORD *)v7 - 1);
      if ( (unsigned int)(v23 - v7 - 4) > 0x1F )
        _invalid_parameter_noinfo_noreturn(v27 + 36);
    }
    sub_4064DE(v7);
  }
  return 0;
}

前面有几个函数不知道是啥,通过动态调试,发现第三个函数和输入有关,先猜测是scanf。 经过动态调试后,确定了,最终v25是字符串地址,V26是长度。

接下来就是与将input与SWPU_2019_CTF进行异或操作。

     接下来就是一个看起来很复杂的加密函数sub_4025C0(),由于不懂是啥意思,通过动态调试下断点的方法看看。

        在调用这个函数前。先锁定两个字符串地址。

 

        其中一个是经过前面异或变换的字符串:

 ​

 

       另一个是空的,最终这个函数会将结果放到这个字符串中,因此我们下一个硬件断点。  

 ​​​​​​​

 最终在了这。这一段循环就是一段异或操作。异或的字符串是[esi+eax]。

异或的字符串为: 

 

最后就是和v38往下这一群字符串进行比对了。

 所以说现在就很明确了。写脚本即可。

 附上C语言脚本:

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<iostream>
#include<vector>
using namespace std;

int main() {
	unsigned int fina[10] = { 0xF80F37B3 ,0x5DAEBCBC ,0x864D5ABA ,0xD3629744 ,0x1624BA4F ,0x1A729F0B,0x266D6865,0x67C86BBA };
	unsigned int med[10] = { 0xca3e0c86,0x19aed798,0xa66b77e2,0xb077a16a,0x05379169,0x307bf97a,0x104b5a43,0x28d47d86 };
	char SWPU_2019_CTF[20] = "SWPU_2019_CTF";
	char answer[50] = { 0 };
	for (int i = 0; i < 8; i++) {
		fina[i] = fina[i] ^ med[i];
	}
	for (int i = 0; i < 32; i++) {
		answer[i] = SWPU_2019_CTF[i%13] ^ *((char *)fina + i);
	}
	printf("%s", answer);

}

//ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值