Ollvm去平坦化脱壳
RoarCTF polyre(参考CRC64)
最近复现RoarCTF的polyre时候,发现了ollvm这个保护器挺有意思的,然后参考了师傅们的blog,提出我自己的看法
首先下载D-810。https://gitlab.com/eshard/d810
把文件夹和.py复制到IDA目录的plugin下即可。(最开始我用的7.5然后移动plugins发现在ida里面没有这个d810这个插件,然后我就更换了一个ida8.3版本,发现挺好用的)
这个也可以用虚拟机跑脚本,不过需要安装一个angr的一个库,具体怎么实现的我也没太研究,就知道在虚拟机里面跑一个脚本就行
先查看main函数地址,之后执行命令
python deflat.py -f attachment --addr 0x400620 //0x400620是main函数的地址
启动ida。这是未进行脱壳的进程
这是经过d810去平坦化之后的源码
v10 = 0;
memset(s, 0, 0x30uLL);
memset(s1, 0, sizeof(s1));
printf("Input:");
v11 = s;
__isoc99_scanf("%s", s);
for ( i = 0; ; ++i )
{
v12 = i;
v13 = i < 64;
if ( i >= 64 )
break;
v14 = s[i];
v15 = v14;
if ( v14 == 10 )
{
v16 = &s[i];
*v16 = 0;
break;
}
v17 = i + 1;
}
for ( j = 0; ; ++j )
{
v18 = j;
v19 = j < 6;
if ( j >= 6 )
break;
v20 = s;
v4 = *(_QWORD *)&s[8 * j];
for ( k = 0; ; ++k )
{
v21 = k;
v22 = k < 64;
if ( k >= 64 )
break;
v23 = v4;
v24 = v4 < 0;
if ( v4 < 0 )
{
v25 = 2 * v4;
v26 = 2 * v4;
v4 = (2 * v4) ^ 0xB0004B7679FA26B3LL;
}
else
{
v27 = v4;
v28 = 2 * v4;
v4 *= 2LL;
}
v29 = k;
}
v30 = 8 * j;
v31 = &s1[8 * j];
*(_QWORD *)v31 = v4;
v32 = j + 1;
}
v33 = memcmp(s1, &unk_402170, 0x30uLL);
v34 = v33 != 0;
puts("Correct!");
return v10;
人工调整后可以复现出加密的代码,如下:
#include <bits/stdc++.h>
using namespace std;
unsigned char in[1007],flag[1007];
int len;
int main() {
// in flag: len == 48
memset(in,0,sizeof(in));
memset(flag,0,sizeof(flag));
scanf("%s",in),len=3;
for (int i=0; i<len; i++)
if (in[i]=='\n') in[i]=0;
for (int i=0; i<6; i++) {
cout<<(&in+i*8)<<endl;
__int64 p = *((__int64 *)&in[i*8]);
cout<<p<<endl;
for (int j=0; j<64; j++) {
//encode x64
if (p>=0) p*=2; // p<<=1
else p=p*2^0xB0004B7679FA26B3LL; //p=p<<1^0xB000...
}
*(__int64 *)(&flag[i*8])=p;
}
if (memcmp(flag,encode,48)) puts("Wrong!");
else puts("Correct!");
return 0;
}
exp:
#include <bits/stdc++.h>
using namespace std;
unsigned char encode[48] = { 0x96, 0x62, 0x53, 0x43, 0x6D, 0xF2, 0x8F, 0xBC,
0x16, 0xEE, 0x30, 0x05, 0x78, 0x00, 0x01, 0x52,
0xEC, 0x08, 0x5F, 0x93, 0xEA, 0xB5, 0xC0, 0x4D,
0x50, 0xF4, 0x53, 0xD8, 0xAF, 0x90, 0x2B, 0x34,
0x81, 0x36, 0x2C, 0xAA, 0xBC, 0x0E, 0x25, 0x8B,
0xE4, 0x8A, 0xC6, 0xA2, 0x81, 0x9F, 0x75, 0x55
};
unsigned char flag[48];
int main() {
for (int i=0;i<6;i++) {
__int64 p = *((__int64 *)&encode[i*8]);
for (int j=0;j<64;j++) {
// check the last bit
if (p&1) {
p=((unsigned __int64)p^0xB0004B7679FA26B3LL)/2; // p=(p^0xB000...)>>1
p|=0x8000000000000000; // avoid - to +
}
else p=(unsigned __int64)p/2; // p>>=1;
}
for (int j=0;j<8;j++) printf("%c",(char)p&0xff),p>>=8;
}
return 0;
}
c=[0x96, 0x62, 0x53, 0x43, 0x6D, 0xF2, 0x8F, 0xBC, 0x16, 0xEE,
0x30, 0x05, 0x78, 0x00, 0x01, 0x52, 0xEC, 0x08, 0x5F, 0x93,
0xEA, 0xB5, 0xC0, 0x4D, 0x50, 0xF4, 0x53, 0xD8, 0xAF, 0x90,
0x2B, 0x34, 0x81, 0x36, 0x2C, 0xAA, 0xBC, 0x0E, 0x25, 0x8B,
0xE4, 0x8A, 0xC6, 0xA2, 0x81, 0x9F, 0x75, 0x55, 0xB3, 0x26,
0xFA, 0x79, 0x76, 0x4B, 0x00, 0xB0]
k=8
t=[]
for i in range(0,len(c),k):
tmp=0
for j in range(i,i+k):
tmp+=c[j]*2**(8*j%(k*8))
t.append(tmp)
from Crypto.Util.number import *
key=0xB0004B7679FA26B3
def decrypt(data):
for i in range(64):
s=data&1
if s==1:
data^=key
data//=2
if s == 1:
data |= 0x8000000000000000
return data
flag=b''
for a in t:
tmp=decrypt(a)
flag+=long_to_bytes(tmp)[::-1]
print(flag)