p_info corrupted的一道逆向

这题也是比较有意思的,upx脱壳不了,学到了个新混淆技术可以干扰upx脱壳,如果直接脱壳会报错

这里爆了p_info文件头错误,这里需要二进制编辑软件修改字节

55 50 58 21为upx标识,从21后面数八位,然后修改也是八位,这八位就是p_info损坏的部分

修改啥呢,010翻到文件底部,文件尾部的前八位的四位,我们这里复制,要复制它的hex,

我们选中这四位,再点击010左上角edit编辑,选择copy hex

再向刚才的p_info损坏部分粘贴,这里粘贴也是需要粘贴十六进制,方法同上,是paste

修改完后,就可以发现文件可以正常脱壳了

开始逆向分析,用ida64位打开

shif12查找字符串,这里发现,一个类似base编码,一个假的flag,还有一个good job应该是比较字符串的回显,我们跟进base编码

发现主要函数,v1就是我们要注意的变量,  MException::MException(v0, v1);函数调用,我们跟进下

void checkInput(void)
{
  void *v0; // rdi
  char v1[32]; // [rsp+10h] [rbp-B0h] BYREF
  unsigned __int64 v2; // [rsp+98h] [rbp-28h]

  v2 = __readfsqword(0x28u);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v1);
  std::operator>><char>((std::istream *)&std::cin);
  v0 = _cxa_allocate_exception(0x30uLL);
  MException::MException(v0, v1);
  _cxa_throw(v0, (struct type_info *)&`typeinfo for'MException, MException::~MException);
}

这里发现给a1[10]赋值为6,然后返回值又调用了一个函数,再跟进下

__int64 __fastcall MException::MException(std::exception *a1, __int64 a2)
{
  std::exception::exception(a1);
  *(_QWORD *)a1 = off_5B2190;
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string((char *)a1 + 8, a2);
  *((_DWORD *)a1 + 10) = 6;
  return MException::doSomething(a1);
}

这个函数名叫dosomething,很显然已经暗示的很明显了,这里调用了reverse函数,对四个变量做处理,base_table值为

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

(this+10)-1,之前赋值是6,再减一不就是5吗,这里reverse函数调用了三次,我们跟进下

__int64 __fastcall MException::doSomething(MException *this)
{
  MException::reverse(this, base64Table, 0, *((_DWORD *)this + 10) - 1);
  MException::reverse(this, base64Table, *((_DWORD *)this + 10), 63);
  return MException::reverse(this, base64Table, 0, 63);
}

这里发现对数组数据进行了异或,a2是basetable,这里很显然是将basetable的值改变了,我们用base异或完的表对上面字符串进行base解密就是flag

__int64 __fastcall MException::reverse(MException *this, char *a2, unsigned int a3, int a4)
{
  __int64 result; // rax

  while ( 1 )
  {
    result = a3;
    if ( (int)a3 >= a4 )
      break;
    a2[a3] ^= a2[a4];
    a2[a4] ^= a2[a3];
    a2[a3++] ^= a2[a4--];
  }
  return result;
}
#include<stdio.h>
int main()
{
	char base_table[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	int i=0;
	int b=64;
	int x=5;
	while(1)
	{
		if(i>=x)
		{
			break;
		}
		base_table[i]^=base_table[x];
		base_table[x]^=base_table[i];
		base_table[i++]^=base_table[x--];
	}
	puts(base_table);
	x=6;
	i=63;
	while(1){
		if(x>=i)
		{
			break;
		}
		base_table[x]^=base_table[i];
		base_table[i]^=base_table[x];
		base_table[x++]^=base_table[i--];	
	}
	puts(base_table);
	b=63;
	i=0;
while(1){
	if(i>=b)
		{
			break;
		}
		base_table[i]^=base_table[b];
		base_table[b]^=base_table[i];
		base_table[i++]^=base_table[b--];
	}
	puts(base_table);
	return 0;
 } 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值