这题也是比较有意思的,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;
}