-
-
[原创]stolen code 最简单的实现--jmp 乱序
-
发表于:
2007-8-18 20:01
11821
-
[原创]stolen code 最简单的实现--jmp 乱序
//在 x 中查找 y, 查找成功索引,否则返回 -1
static DWORD _2find(DWORD x[], DWORD l, DWORD y)
{
DWORD low, high, mid;
low = 0;
high = l - 1;
while ( low <= high )
{
mid = (high + low) >> 1;
if ( x[mid] == y )
return mid;
if ( y > x[mid] )
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
/*
CONTS PBYTE psrc 要抽代码的地方
PBYTE pdst 代码经过处理后存放的地方
DWORD Offset 被抽代码和存放代码之间偏移,注:不一定是 pdst - psrc, 有些难表达
int line 要抽的代码行数
返回第一条指令的位置
*/
//打乱原始指令序列
/*
DWORD StolenCode(CONST PBYTE psrc, PBYTE pdst, DWORD offset, DWORD line, PDWORD size)
{
DWORD a[100], b[100], l[100];
PBYTE p1, p2;
DWORD i, j;
j = 0;
for ( i = 0; i < line; ++i )
{
a[i] = j; //原始指令的原始偏移位置
b[i] = (DWORD)-1;
xde_instr instr;
l[i] = xde_disasm(psrc + j, &instr); //获取指令长度
if ( l[i] == 0 )
break;
j += l[i];
}
p2 = pdst;
for ( j = 0; j < i; ++j ) //打乱指令顺序,然后用 jmp 指令串连起来
{
int k;
do {
k = rand() % i;
} while ( b[k] != (DWORD)-1 );
p1 = psrc + a[k];
b[k] = p2 - pdst + 1;
if ( *p1 == 0xEB ) { //把短跳转指令修改为长跳转指令
p2 += 3; // 3 = 5 - l[k]
}
else if ( *p1 >= 0x70 && *p1 <= 0x7F ) {
p2 += 4; // 4 = 6 - l[k]
}
else if ( *p1 == 0xE2 ) {
p2 += 5; //5 = 7 - l[k]
}
else if ( *p1 == 0xE3 ) { //jcxz
p2 += 6; //6 = 8 - l[k]
}
else if ( *p1 == 0xE0 || *p1 == 0xE1 ) {
p2 += 7; //7 = 9 - l[k]
}
else {
*p2++ = (BYTE)rand(); //junk
memcpy(p2, p1, l[k]);
}
p2 += l[k] + 5;
}
*size = p2 - pdst; //变化后数据实际大小
for ( j = 0; j < i; ++j ) //修正跳转
{
DWORD w1 = l[j];
DWORD w2 = l[j];
p1 = psrc + a[j];
p2 = pdst + b[j];
if ( *p1 == 0xEB || (*p1 >= 0x70 && *p1 <= 0x7F) || (*p1 >= 0xE0 && *p1 <= 0xE3) ) //8 位相对跳转
{
if ( *p1 == 0xEB )
{
w2 = 5; //修改模式后, 这条指令的长度
*p2++ = 0xE9;
}
else if ( *p1 >= 0x70 && *p1 <= 0x7F )
{
w2 = 6;
*p2++ = 0x0F;
switch ( *p1 )
{
case 0x70: *p2 = 0x80; break; //jo rel8 --> jo rel32
case 0x71: *p2 = 0x81; break; //jno rel8 --> jno rel32
case 0x72: *p2 = 0x82; break; //jnae rel8 --> jnae rel32
case 0x73: *p2 = 0x83; break; //jnb rel8 --> jnb rel32
case 0x74: *p2 = 0x84; break; //jz rel8 --> jz rel32
case 0x75: *p2 = 0x85; break; //jnz rel8 --> jnz rel32
case 0x76: *p2 = 0x86; break; //jna rel8 --> jna rel32
case 0x77: *p2 = 0x87; break; //jnbe rel8 --> jnbe rel32
case 0x78: *p2 = 0x88; break; //js rel8 --> js rel32
case 0x79: *p2 = 0x89; break; //jns rel8 --> jns rel32
case 0x7A: *p2 = 0x8A; break; //jp rel8 --> jp rel32
case 0x7B: *p2 = 0x8B; break; //jpo rel8 --> jpo rel32
case 0x7C: *p2 = 0x8C; break; //jnge rel8 --> jnge rel32
case 0x7D: *p2 = 0x8D; break; //jnl rel8 --> jnl rel32
case 0x7E: *p2 = 0x8E; break; //jng rel8 --> jng rel32
case 0x7F: *p2 = 0x8F; break; //jnle rel8 --> jnle rel32
}
++p2;
}
else
{
switch ( *p1 )
{
case 0xE0:
//loopne -->
//$ jz $ + 8
//$ + 2 dec ecx
//$ + 3 jnz xxxxxxxx
//$ + 8 ????????????????
*p2++ = 0x74; *p2++ = 0x07; *p2++ = 0x49; *p2++ = 0x0F; *p2++ = 0x85;
w2 = 9;
break;
case 0xE1:
//loope -->
//$ jnz $ + 8
//$ + 2 dec ecx
//$ + 3 jnz xxxxxxxx
//$ + 8 ????????????????
*p2++ = 0x75; *p2++ = 0x07; *p2++ = 0x49; *p2++ = 0x0F; *p2++ = 0x85;
w2 = 9;
break;
case 0xE2:
//loop -->
//$ dec ecx
//$ + 1 jnz xxxxxxxx
*p2++ = 0x49; *p2++ = 0xF; *p2++ = 0x85;
w2 = 7;
break;
case 0xE3:
//jcxz -->
//$ test ecx, ecx
//$ + 2 jz xxxxxxxx
*p2++ = 0x85; *p2++ = 0xC9; *p2++ = 0x0F; *p2++ = 0x84;
w2 = 8;
}
}
DWORD k = _2find(a, i, a[j] + (char)p1[1] + l[j]);
if ( (DWORD)-1 == k )
{ //目标指令没有抽到
DWORD z = offset + b[j] - a[j] + w2 - w1 - (char)p1[1];
*(PDWORD &)p2 = 0 - z;
}
else {
*(PDWORD &)p2 = b[k] - b[j] - w2;
}
p2 += sizeof (DWORD);
}
else if ( *p1 == 0xE9 || *p1 == 0xE8 || (*(PDWORD)p1 >= 0x800F && *(PDWORD)p1 <= 0x8F0F) ) //32 位相对跳转
{
DWORD k = _2find(a, i, a[j] + *(PDWORD)(p1 + 1) + l[j]);
p2 += l[j] == 5 ? 1 : 2;
if ( (DWORD)-1 == k )
{
DWORD z = offset + b[j] - a[j] - *(int*)(p1 + 1);
*(PDWORD &)p2 = 0 - z;
}
else {
*(PDWORD &)p2 = b[k] - b[j] - w1;
}
p2 += sizeof (DWORD);
}
else {
p2 += l[j];
}
DWORD z = offset + b[j] - a[j] + 5 + w2 - w1;
*p2++ = 0xE9;
*((PDWORD &)p2)++ = j == i - 1 ? 0 - z : b[j + 1] - b[j] - w2 - 5; //修改 jmp 跳转
}
return b[0];
}
[注意]APP应用上架合规检测服务,协助应用顺利上架!