//////////////////////////////////////////////////////////////
// arm4.00.0053客户版主程序的从双进程到单进程转换的Script自动运行脚本
// 本脚本完成双进程到单进程的自动转换和代码段自动修复功能
// 测试系统:winxpsp1 
// 异常选项中去掉[忽略指定的异常范围],其余全部打勾
// 特别感谢Loveboom王子的帮助,感谢fly的测试。
// by fxyang
// 2005.4.15
//////////////////////////////////////////////////////////////

dbh

var address
gpa "OpenMutexA","kernel32.dll"
bp $RESULT
run

eoe code_1
code_1:
mov address,eip  //获取第一次PREFIX LOCK:异常地址 
esto
cmp eip,address   //自动越过异常
ja begin
esto

//////////////////////////////////////////////////////////
//双进程到单进程的转换
//////////////////////////////////////////////////////////

begin:
  exec
    PUSHAD
    PUSH EDX
    push 0
    push 0
    CALL kernel32.CreateMutexA
    POPAD
    jmp kernel32.OpenMutexA
  ende

//上面的代码就是在Script中运行从双进程到单进程的转换

  bc $RESULT
  gpa "CreateThread","kernel32.dll"
  bp  $RESULT
  eob tmp1
  esto

tmp1:
bc $RESULT
sto
sto
var variant
mov variant,ebp
add variant,18
mov [variant],#04000000#
//修改API参数,让线程挂起来
rtu
sto
sto
mov eax,0
/*
修改下面的跳转,防止程序anti time
00497215  TEST EAX,EAX
00497217  JE SHORT Armadill.00497231
00497219  CALL DWORD PTR DS:[<&KERNEL32.GetTickCou>; kernel32.GetTickCount
0049721F  CMP EAX,DWORD PTR SS:[EBP-114]
00497225  JNB SHORT Armadill.00497231
00497227  PUSH 1
00497229  CALL DWORD PTR DS:[<&KERNEL32.Sleep>]    ; kernel32.Sleep
0049722F  JMP SHORT Armadill.0049720E

*/
//////////////////////////////////////////////////////////////////
//anti OutputDebugStringA 修复
//////////////////////////////////////////////////////////////////
var setc1

gpa "OutputDebugStringA","kernel32.dll"
mov address,0
mov setc1,$RESULT
bp  setc1
eob setcode1
run

setcode1:
inc address
mov [eax],#00000000#
cmp address,2
je setcode2
run

setcode2:
rtu
gpa "GetVersion","kernel32.dll"
bp $RESULT
eob tmp2
run

tmp2:
bc $RESULT
rtu
gpa "GetPrivateProfileStringA","kernel32.dll"
bp $RESULT
eob tmp3
run

tmp3:
bc $RESULT
rtu
gpa "sprintf","msvcrt.dll"
bp $RESULT
eob tmp4
run

tmp4:
rtu
bc $RESULT
rtr
sto
gpa "memset","msvcrt.dll"
bp $RESULT
eob lbl1
esto

lbl1:
rtu
rtr
sto
mov address,0
gpa "RtlLeaveCriticalSection","ntdll"
bp $RESULT
eob lbl7
run

lbl7:
inc address
cmp address,2
je lbl8
run

lbl8:
bc $RESULT
mov address,0
gpa "memset","msvcrt.dll"
bp $RESULT
eob lbl2
run

lbl2:
bc $RESULT
rtu
mov address,eip
add address,2af
bp address
eob lbl9
run

lbl9:
bc address
mov eax,0       // <--anti 1
///////////////////////////////////////////////////////////
//上面一段都是为了定位到代码解码前的双进程效验
/*
00EF7B7A  MOV EAX,DWORD PTR DS:[F123D0]
00EF7B7F  MOV AL,BYTE PTR DS:[EAX+3D57]
00EF7B85  MOV BYTE PTR SS:[EBP+FFFF9CCC],AL
00EF7B8B  MOVZX EAX,BYTE PTR SS:[EBP+FFFF9CCC]
00EF7B92  TEST EAX,EAX  //修改这个值为0
00EF7B94  JE 00EF7CB4  //这里必须跳
*/
///////////////////////////////////////////////////////////


gpa "VirtualProtect","kernel32.dll"
var x
mov x,$RESULT
bp x
eob ll1
run

ll1:
rtu
sto
gpa "memcpy","msvcrt"
bp $RESULT
eob code1
run

code1:
rtu
mov [0044bd00],#609C8B5C243081C3001040008D5BFC8B1331108D40043D00BC44007CF4909D61C3#
sub esp,4
mov [esp],eip
mov eip,0044bd00
eob exitc
run
/////////////////////////////////////////////////////////////////////////
//上面这段是修复代码段解码后由于双进程转换到单进程后父进程未参与解码,
//引起代码段未正确还原
//第一次的VirtualProtect函数正好修改了代码段的属性为可写,是修复的好机会
//到这里代码段的还原工作完成:)
/////////////////////////////////////////////////////////////////////////

exitc:
bc x
rtu
msg "代码段已正确还原,下面是IAT还原,到达OEP地址。请努力!"

pause

脚本中的标签是调试时随便起的,可能不规范,不想修改了请见谅。
本脚本很容易修改成arm4.0版的其他加壳程序的脱壳辅助