ctf——逆向新手题目11 (csaw2013reversing2) WP

首先将下载的文件打开运行
在这里插入图片描述
确实如题目描述所说运行可以得到flag,但是却为乱码
那就先用Exeinfo PE查看信息
在这里插入图片描述
这次为c++编写的32位程序,直接用ida32打开
进入后直接查看主函数的伪代码
在这里插入图片描述
这个主函数看起来还是比较复杂的
先查看开头的HeapCreate()函数和heapAlloc()函数的作用,百度了解到这两个函数实际上就是申请了内存空间的(https://www.cnblogs.com/lancidie/archive/2011/02/12/1952356.html)
然后看一下memcpy_s()函数,实际作用就是进行的字符串的拷贝
在这里插入图片描述
代码中的作用就是将 unk_409B10 中的字符串拷贝到IpMem
跟进后查看
在这里插入图片描述
接下来到了 if 条件处

if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, lpMem);
    ExitProcess(0xFFFFFFFF);
  }

先查看if判断的两个条件

int sub_40102A()
{
  char v0; // t1
  v0 = *(_BYTE *)(*(_DWORD *)(__readfsdword(0x18u) + 48) + 2);
  return 0;
}

第一个条件返回值为0,就不用看了
第二个条件 IsDebuggerPresent 百度了解到这个函数是用于反调试,当检测到程序被调试时,就会结束其进程或不按正常流程运行,而达到反调试的作用
先不看 if 中的语句,继续往后看

MessageBoxA(0, lpMem + 1, "Flag", 2u);
HeapFree(hHeap, 0, lpMem);
HeapDestroy(hHeap);

MessageBoxA函数作用是进行一个输出,进行输出flag
我们猜测 IpMem 中有我们要的 flag
先将之前 unk_409B10 中的数据导出
写脚本进行输出

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
	int lpMem[]=
	{
	  0xBB, 0xCC, 0xA0, 0xBC, 0xDC, 0xD1, 0xBE, 0xB8, 0xCD, 0xCF,
	  0xBE, 0xAE, 0xD2, 0xC4, 0xAB, 0x82, 0xD2, 0xD9, 0x93, 0xB3,
	  0xD4, 0xDE, 0x93, 0xA9, 0xD3, 0xCB, 0xB8, 0x82, 0xD3, 0xCB,
	  0xBE, 0xB9, 0x9A, 0xD7, 0xCC, 0xDD
	};
	for (int i = 0; i < 36; i++)
	{
		printf("%c", lpMem[i]);
	}
	return 0;
}

运行出来还是乱码,毕竟不可能让我们这么容易出结果
在这里插入图片描述

 sub_401000(v3 + 4, lpMem);

此时退回之前没看的 if 条件内部,其实sub_401000调用了lpMem
跟进去查看

unsigned int __fastcall sub_401000(int a1, int a2)
{
  int v2; // esi
  unsigned int v3; // eax
  unsigned int v4; // ecx
  unsigned int result; // eax

  v2 = dword_409B38;
  v3 = a2 + 1 + strlen((const char *)(a2 + 1)) + 1;
  v4 = 0;
  result = ((v3 - (a2 + 2)) >> 2) + 1;
  if ( result )
  {
    do
      *(_DWORD *)(a2 + 4 * v4++) ^= v2;
    while ( v4 < result );
  }
  return result;
}

这里对 v2 进行了赋值,继续跟进去查看 dword_409B38
在这里插入图片描述
后面发现这个可以转变为数据
在这里插入图片描述
分析这段代码,是lpMem进行依次异或v2中的数,根据这个写出脚本

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
	int lpMem[]=
	{
	  0xBB, 0xCC, 0xA0, 0xBC, 0xDC, 0xD1, 0xBE, 0xB8, 0xCD, 0xCF,
	  0xBE, 0xAE, 0xD2, 0xC4, 0xAB, 0x82, 0xD2, 0xD9, 0x93, 0xB3,
	  0xD4, 0xDE, 0x93, 0xA9, 0xD3, 0xCB, 0xB8, 0x82, 0xD3, 0xCB,
	  0xBE, 0xB9, 0x9A, 0xD7, 0xCC, 0xDD
	};
	int v2[]=
	{
	  0xBB, 0xAA, 0xCC, 0xDD
	};
	for (int i = 0; i < 36; i++)
	{
		printf("%c", lpMem[i] ^ v2[i % 4]);
	}
	return 0;
}

运行得出本题flag
在这里插入图片描述
其实本题还可以用动态调试,但由于汇编了解并不多,这里并没有进行动态分析,等之后汇编了解差不多,再用动态调试去解这道题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值