Arm壳的 StolenCode ,很有规律,想试手编程,OD的纯脚本运行会慢得很惊人,至少在我的慢机很常见
我的 Dll Delphi源码 还没完成的。。。,只做了一部分,小测试过一下,不是很好
贴上来:
先附用 OllyMachines 记录数据的脚本
// 一个字,“乱”
// Arm 的StolenCode 记录数据脚本
__asm
{
pushfd
pushad
push 40
push 1000
push 20000
push 0
call KERNEL32.VirtualAlloc
}
cmp eax, 0
je verr
mov reg11, eax // dwOpLenTab 的值
mov reg15, eax
invoke logtext, "★★★★★ 成功申请下面的空间地址:"
invoke loglong, reg11
invoke GotoDumpAddr, reg11
__asm
{
popad
popfd
}
add reg15, 0x10000 // 划分一个空间给 记录 dwLogAddressTab 值的表
mov reg10, 0x587000 // StolenCode 节首地址 dwStolenCodeSection 的值
mov reg00, reg10
mov reg12, 0
mov reg13, 0
mov reg14, reg11
invoke GotoDumpAddr, reg11
loop:
cmp reg10, 0x596FC2 // 此处是比较 StolenCode 块的结束地址
je end
mov reg16, reg10
invoke ReadMemLong, reg16, 1
cmp reg00, 0xE9
jne skip
inc reg16
invoke ReadMemLong, reg16, 4
cmp reg00, 0
je skip
dec reg16
mov reg18, reg00
invoke WriteMemLong, reg15, reg16, 4
add reg15, 4
add reg16, 5
add reg16, reg18 // 取得返回地址
checking:
invoke GetPrevOpAddr, reg16, 1 // 逆向扫描返回地址
mov reg16, reg00
invoke ReadMemLong, reg16, 1
cmp reg00, 0xE9
jne checking // 直到找到JMP指令
invoke WriteMemLong, reg15, reg16, 4
add reg15, 4
skip:
invoke GetNextOpAddr, reg10, 1
mov reg12, reg00
sub reg12, reg10
mov reg10, reg00
invoke WriteMemLong, reg11, reg12, 1
inc reg11
inc reg13
jmp loop
end:
invoke LogText, "☆☆☆☆☆记录指令数量为:"
invoke LogLong, reg13
invoke DumpMem, reg14, 0x20000, "OpLen_Tab.bin"
invoke msg, "Well Done!"
halt
verr:
__asm
{
popad
popfd
}
invoke msg, "发生一个申请内存的错误!"
halt
///////////////////////////////////////////////////////
library RestoreStolen;
uses
SysUtils,
Windows,
Classes;
{$R *.RES}
// 小弟感觉这是自己真正的编程的头一次开始,所以写得很烂...
// 变量定义得比较奢侈,牛哥们可以指点指点..., 有值得优化的地方指点指点
// Nop 垃圾指令还在测试中,所以还缺一个移动还原动作的代码。。。
Type
Tpackvar = record
PatchAddr :^Dword; // 这个正式还原时用,暂未用
LenTab :Dword; // 指令长度表起始地址
Sbegin :Dword; // 一个小的 StolenCode 块的起始地址
Send :Dword; // 一个小的 StolenCode 块的结束地址
pNextAddr :^Dword; // 指向第 n 个块表的指针
count :Dword; // 作临时计算地址过渡用
len :Byte; // 保存取指令长度表一个索引指向的size
abyte :Byte; // 临时用的字节保存变量
aword :Word; // 作用同上(字),可能会用上
adword :Dword; // 作用同上(双字),可能会用上
pLen :^Byte; // 全局用的指令长度表指针变量
pbyte :^Byte; // 单个 StolenCode 块的指针变量
tbyte :^Byte; // pbyte 某位置的临时保存
cbyte :^Byte; // pbyte 某位置的临时保存
pword :^Word; // 作保存,需要时取用
tword :^Word; // 作用同上
cword :^Word;
pdword :^Dword; // 作保存,需要时取用
tdword :^Dword; // 作用同上
cdword :^Dword;
temp :Pointer; // 保存指针变量,作取用
i : integer; // 这个没有用上,以后不知是否会用
end;
procedure Checkdust2(myvar: Tpackvar);// 2字节的公用调用检测是否配对 的过程
begin
myvar.tword := Pointer(myvar.pLen) ; //取当前指令长度表指针
myvar.tbyte := Pointer(myvar.pLen) ;
myvar.cword := myvar.temp ;
While Dword( myvar.cword ) < myvar.Send do
begin
inc (myvar.tbyte );
myvar.abyte := myvar.tbyte^ ;
myvar.count := Dword( myvar.cword ) + myvar.abyte ;
myvar.cword := Pointer( myvar.count );
if ( myvar.abyte =2 ) and ( myvar.pword^ = myvar.cword^ )then
begin
myvar.pword^ := $9090 ;
myvar.cword^ := $9090 ;
break;
end;
end;
end;
Function RestoreStolenCode( dwOpLenTab, dwLogAddressTab, dwStolenCodeSection: Dword ) : boolean ; stdcall ;
var
handle: Thandle;
myvar : Tpackvar;
flag : boolean;
begin
flag := false ;
Result := True ;
try
begin
// 下面初始化
myvar.pNextAddr := Pointer( dwLogAddressTab ) ;
myvar.Sbegin := dwStolenCodeSection ;
myvar.LenTab := dwOpLenTab ;
myvar.count := 0;
myvar.pLen := Pointer( myvar.LenTab ) ;
// 大循环开始
{
While myvar.pLen^ <> 0 do // 外循环,若中间只存在 Nop 指令的成对 push pop 处理
begin
myvar.Sbegin := myvar.pNextAddr ;
myvar.tdword := Pointer( myvar.patchaddr );
}
While myvar.pNextAddr^ <> 0 do // 中循环,找出壳的某个 StolenCode 块的范围
begin
myvar.len := myvar.pLen^;
myvar.pbyte := Pointer( myvar.Sbegin );
myvar.Send := myvar.pNextAddr^ ; // 传送表项的块结束地址
While Dword( myvar.pbyte ) < myvar.Send do // 内块循环:相邻的垃圾指令 Nop 掉
begin
myvar.Len := myvar.pLen^ ;
myvar.temp := myvar.pbyte ;
myvar.pword := myvar.temp ;
myvar.pdword := myvar.temp ;
Case myvar.len of
1:
begin
if myvar.pbyte^ in [ $91..$97 ] then //如果是32位寄存器 xchg 指令,就查找是否有成对,有则 Nop 掉
begin
myvar.tbyte := Pointer(myvar.pLen) ; //取当前指令长度表指针
myvar.cbyte := myvar.temp ;
While Dword( myvar.cbyte ) < myvar.Send do
begin
inc ( myvar.tbyte );
myvar.abyte := myvar.tbyte^ ;
myvar.count := Dword( myvar.cbyte ) + myvar.abyte ; // 下一个指令地址 = 本指令地址+ 指令长度
myvar.cbyte := Pointer( myvar.count );
if ( myvar.abyte =1 ) and ( myvar.pbyte^ = myvar.cbyte^ )then
begin
myvar.pbyte^ := $90 ;
myvar.cbyte^ := $90 ;
break;
end;
end;
end; // 32位寄存器 xchg 指令判断结束
if myvar.pbyte^ in [ $50..$57 ] then // 如果是相邻的Push Pop 32位寄存器指令,就 Nop 掉
begin
myvar.abyte := myvar.pbyte^;
inc(myvar.pbyte);
if (myvar.pbyte^ - 8) = myvar.abyte then
myvar.pword^ := $9090 ;
end; // Push Pop 判断结束
end;
2:
begin // 两字节的垃圾代码有很多
case myvar.pbyte^ of
$0F: // 是否32位寄存器的 bswap 指令,是则查找它有否配对,有则 Nop
begin
inc( myvar.pbyte);
if myvar.pbyte^ in [$C8..$CF] then
CheckDust2(myvar);
end;
$66:
begin
inc( myvar.pbyte);
if myvar.pbyte^ = $90 then // 特殊情况的 Nop 指令
myvar.pword^ := $9090 ;
if myvar.pbyte^ in [$91..$97] then // xchg 16位寄存器
CheckDust2(myvar);
end;
$70..$7F,$EB,$E3:
begin // 零距离的 Jmp 类指令
myvar.cbyte := myvar.temp ;
inc( myvar.pbyte);
case myvar.pbyte^ of
0:
begin
myvar.pword^ := $9090 ; // 不是则只 Nop 本条指令
end;
2:
begin
inc( myvar.pbyte );
if myvar.pbyte^ = myvar.cbyte^ then //是否同类的垃圾Short jmp
myvar.pdword^ := $90909090 ;
end;
end; // 零距离的 Jmp 类指令处理结束
$87:
begin
inc( myvar.pbyte);
if myvar.pbyte^ in [$C0, $C9,$D2,$DB,$E4,$ED,$F6,$FF] then // xchg 相同寄存器 ecx..edi
myvar.pword^ := $9090
else
begin
if myvar.pbyte^ in [$C1..$C8,$CA..$CF,$D0..$DA,$DC..$DF,$E0..$E3,$E5..$EF,$F0..$F5,$F7..$FE] then
CheckDust2(myvar); // 检测是否有成对
end;
end;
$8B:
begin
inc( myvar.pbyte );
if myvar.pbyte^ in [$C0,$C9,$D2,$DB,$E4,$ED,$F6,$FF] then // mov 同等32位寄存器,如:mov eax,eax
myvar.pword^ := $9090 ;
end;
$F7:
begin
inc( myvar.pbyte );
if myvar.pbyte^ in [ $D0..$D7 ] then // not 32位寄存器,是否有成对
CheckDust2(myvar);
end;
end; // case of 两字节处理块结束
end; // 两字节处理 End
3: // 三字节的垃圾代码也有,这个会有很多
begin
case myvar.pbyte^ of
$66:
begin
inc( myvar.pbyte );
if myvar.pbyte^ = $87 then
begin
inc( myvar.pbyte );
if myvar.pbyte^ in [ $F1..$F3,$F9..$FB ]then
begin
myvar.pword^ := $9090 ;
myvar.pbyte^ := $90 ;
end
end;
end;
$67:
begin
myvar.count := dword( myvar.pbyte ) ;
inc( myvar.count ) ;
myvar.pword := Pointer( myvar.count ) ;
if myvar.pword^ = $E300 then
begin
myvar.pbyte^ := $90 ;
myvar.pword^ := $9090 ;
end;
end;
end;
end;
5:
begin
if myvar.pbyte^ = $0E9 then // 是否绝对偏移跳转
begin
myvar.tbyte := myvar.temp ;
inc( myvar.tbyte );
myvar.pdword := Pointer( myvar.tbyte );
if myvar.pdword^ = 0 then // 是否为垃圾跳转,是则填充nop
begin
myvar.pbyte^ := $90 ;
myvar.pdword^ := $90909090 ;
end;
end;
end;
end; // case of End
myvar.count := Dword( myvar.temp ) + myvar.pLen^ ;
myvar.pbyte := Pointer( myvar.count ) ; // 同步移动到下一条指令的地址
inc( myvar.pLen ); // 指令长度表+1,指向下一条指令的长度
end; // While 内
inc( myvar.pLen ) ;
myvar.Sbegin := myvar.Send +5 ;
inc( myvar.pNextAddr ) ;
inc( myvar.pNextAddr ) ;
end; // While 中
{
end; // While 外
}
flag := true;
end;
finally
if not flag then
begin
handle := 0 ;
MessageBoxA(handle, Pchar('可能发生访问异常错误,请重来确定参数可用再试!'), Pchar('异常错误:'), MB_OK);
Result := false ;
end;
end;
end;
exports
RestoreStolenCode ;
begin
end.
///////////////////////////////////////////
贴一下 Arm StolenCode的垃圾特征:
00587000 6A FF push -1
00587002 66:96 xchg ax,si
00587004 0FC9 bswap ecx
00587006 0FC9 bswap ecx
00587008 66:96 xchg ax,si
0058700A 68 B2E45200 push 52E4B2 ; 入口地址
0058700F - E9 A1A0E7FF jmp 004010B5 ; SWFDECOM.004010B5
00587014 50 push eax
00587015 64:8925 00000000 mov dword ptr fs:[0],esp
0058701C 51 push ecx
0058701D 56 push esi
0058701E 57 push edi
0058701F 8B7C24 1C mov edi,dword ptr ss:[esp+1C]
00587023 8BF1 mov esi,ecx
00587025 87FE xchg esi,edi
00587027 87FE xchg esi,edi
00587029 8BCF mov ecx,edi
0058702B - E9 92A0E7FF jmp 004010C2 ; SWFDECOM.004010C2
00587030 C74424 14 00000000 mov dword ptr ss:[esp+14],0
00587038 F7D1 not ecx
0058703A 66:92 xchg ax,dx
0058703C 96 xchg eax,esi
0058703D 96 xchg eax,esi
0058703E 66:92 xchg ax,dx
00587040 87DB xchg ebx,ebx
00587042 F7D1 not ecx
00587044 C707 08F25400 mov dword ptr ds:[edi],54F208
0058704A - E9 8DA0E7FF jmp 004010DC ; SWFDECOM.004010DC
0058704F 0FC8 bswap eax
00587051 78 00 js short 00587053 ; SWFDECOM.00587053
00587053 0FC8 bswap eax
00587055 68 94000000 push 94
0058705A - E9 8DA0E7FF jmp 004010EC ; SWFDECOM.004010EC
0058705F C64424 14 01 mov byte ptr ss:[esp+14],1
00587064 - E9 98A0E7FF jmp 00401101 ; SWFDECOM.00401101
00587069 C706 B8F25400 mov dword ptr ds:[esi],54F2B8
0058706F 89BE 90000000 mov dword ptr ds:[esi+90],edi
00587075 - E9 93A0E7FF jmp 0040110D ; SWFDECOM.0040110D
0058707A 8977 50 mov dword ptr ds:[edi+50],esi
0058707D 8BC7 mov eax,edi
0058707F 5F pop edi
00587080 50 push eax
00587081 0FCF bswap edi
00587083 87FE xchg esi,edi
00587085 87FE xchg esi,edi
00587087 71 00 jno short 00587089 ; SWFDECOM.00587089
00587089 0FCF bswap edi
0058708B 75 02 jnz short 0058708F ; SWFDECOM.0058708F
0058708D 75 41 jnz short 005870D0 ; SWFDECOM.005870D0
0058708F 58 pop eax
00587090 5E pop esi
00587091 64:890D 00000000 mov dword ptr fs:[0],ecx
00587098 - E9 84A0E7FF jmp 00401121 ; SWFDECOM.00401121
0058709D 8B08 mov ecx,dword ptr ds:[eax]
0058709F 91 xchg eax,ecx
005870A0 66:87F3 xchg bx,si
005870A3 7C 02 jl short 005870A7 ; SWFDECOM.005870A7
005870A5 7C 0C jl short 005870B3 ; SWFDECOM.005870B3
005870A7 51 push ecx
005870A8 8BFF mov edi,edi
005870AA 59 pop ecx
005870AB 66:87F3 xchg bx,si
005870AE 91 xchg eax,ecx
005870AF 8B11 mov edx,dword ptr ds:[ecx]
005870B1 50 push eax
005870B2 - E9 F2A1E7FF jmp 004012A9 ; SWFDECOM.004012A9
005870B7 8B01 mov eax,dword ptr ds:[ecx]
005870B9 8B10 mov edx,dword ptr ds:[eax]
005870BB 51 push ecx
005870BC 8BC8 mov ecx,eax
005870BE - E9 01A2E7FF jmp 004012C4 ; SWFDECOM.004012C4
005870C3 6A FF push -1
005870C5 66:87D1 xchg cx,dx
005870C8 8BC9 mov ecx,ecx
005870CA 73 02 jnb short 005870CE ; SWFDECOM.005870CE
005870CC 73 6C jnb short 0058713A ; SWFDECOM.0058713A
005870CE 66:87D1 xchg cx,dx
005870D1 68 08E85200 push 52E808
005870D6 - E9 FAA1E7FF jmp 004012D5 ; SWFDECOM.004012D5
005870DB 50 push eax
005870DC 64:8925 00000000 mov dword ptr fs:[0],esp
005870E3 51 push ecx
005870E4 56 push esi
005870E5 8BF1 mov esi,ecx
005870E7 66:96 xchg ax,si
005870E9 F7D3 not ebx
005870EB 66:90 nop
005870ED F7D3 not ebx
005870EF 66:96 xchg ax,si
005870F1 57 push edi
005870F2 897424 08 mov dword ptr ss:[esp+8],esi
005870F6 - E9 E7A1E7FF jmp 004012E2 ; SWFDECOM.004012E2
// 当然还有,不全贴了..