目录
0.<什么是乱序>
1.<乱序的步骤>
2.<代码流程图的构建>
3.<开始乱序>
4.<YY>
正文
0.什么是乱序
乱序就是打乱原来的流程。
很多朋友逆向程序时,会把一个程序直接丢到IDA里会出现一副流程图。我们现在要做的就是把这副
流程图打乱。但是并不影响原先流程的逻辑。乱序的原理其实比较简单。说白了就是做HOOK然后填充
花指令。最后在跳转会原先的地址。
1.乱序的步骤
0.把正常代码流程的CALL/JMP/JCC的指令,全部都找出来。
1.对上述进行的位置,进行筛选,如果是8位跳转直接过滤,如果是16位跳转计算偏移空间是否足够
跳转到花指令的偏移。如果是32位的情况直接发通行证。
2.添加一个新节或者利用其它感染方式增加一块可用的区域做存储花指令用。
3.遍历0和1生存的结构。当遇到有偏移时。记录原先要跳转的地方。将原先的偏移替换成花指令空间
的位置。最后在花指令末尾添加一个跳入到原先跳转地址的偏移(一般都是向上跳,新增的区域一般
都处于最后的内存空间).
4.验证花指令的剩余空间是否足够,以便判断是否停止HOOK。
当然你也可以加入一些随机判断,某条跳转是否进行乱序。有些则不用。
2.代码流程图的构建
原理很简单,利用反汇编引擎,开始遍历要乱序的地址和长度。一步一步的找出所有合适的跳转类型指令
代码如下
// 这个是流程图的结构,因为用不到动态转载,所以只记录偏移性质的跳转
typedef struct _CODE_FLOW_NODE
{
struct _CODE_FLOW_NODE *pNext;//下一个节点
BOOL bGoDown;//是否向下跳
DWORD dwBits;//跳转范围
DWORD dwType;//指令类型
BOOL bFar;//是否是远跳
DWORD dwMemoryAddress;//当前内存地址
LPBYTE pFileAddress;//当前文件地址
DWORD dwGotoMemoryAddress;//跳转后的内存地址
LPBYTE pGotoFileAddress;//跳转后的文件地址
DWORD dwInsLen;//指令长度
union
{
BYTE bOffset;
WORD wOffset;
DWORD dwOffset;
};//偏移
} CODE_FLOW_NODE, *PCODE_FLOW_NODE;
// 下面的代码利用了udis86反汇编引擎。个人觉的不错。尤其是直接做反汇编器使用时
// CxPeDiy是定义的一个操作PE文件的集合类。做一些PE结构操作。自己动手吧。
// 代码不算复杂。如果你有个大屏幕的话看起来会简单些。如果像我一样在一台T61上
// 工作。那实在有些不便了
PCODE_FLOW DrawCodeFlow(CONST LPBYTE pMem, CONST LPBYTE pStart, DWORD dwSize)
{
PCODE_FLOW pCodeFlow = new CODE_FLOW;
if (pCodeFlow == NULL)
return NULL;
ZeroMemory(pCodeFlow, sizeof(CODE_FLOW));
CxPeDiy PeDiy;
// 获取一些基本信息
DWORD dwImageBase = PeDiy.GetNtHeader(pMem)->OptionalHeader.ImageBase;
// 初始化反汇编引擎
ud_t ud_obj;
ud_init(&ud_obj);
ud_set_input_buffer(&ud_obj, pStart, dwSize);
ud_set_mode(&ud_obj, 32);
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
if (pCodeFlow->ErrDisassembleAddress.Init(0x1000) == FALSE)
return NULL;
PCODE_FLOW_NODE pCodeFlowHeader = NULL, *pCodeFlowNode = &pCodeFlowHeader;
LPBYTE pCurr = pStart;
while (ud_disassemble(&ud_obj) != 0)
{
// printf("\t%s\n", ud_insn_asm(&ud_obj));
if (ud_obj.mnemonic == UD_Iinvalid)
{
// 反汇编出现错误
pCodeFlow->ErrDisassembleAddress.PutIntoQueue((QUEUE_ELEMENT)pCurr);
}
else
{
// 判断是否是跳转地址
switch (ud_obj.mnemonic)
{
case UD_Ijo:
case UD_Ijno:
case UD_Ijb:
case UD_Ijae:
case UD_Ijz:
case UD_Ijnz:
case UD_Ijbe:
case UD_Ija:
case UD_Ijs:
case UD_Ijns:
case UD_Ijp:
case UD_Ijnp:
case UD_Ijl:
case UD_Ijge:
case UD_Ijle:
case UD_Ijg:
case UD_Ijcxz:
case UD_Ijecxz:
case UD_Ijrcxz:
{
// 分配节点内存
*pCodeFlowNode = new CODE_FLOW_NODE;
(*pCodeFlowNode)->bFar = FALSE;
DWORD dwRVA = PeDiy.Raw2Rva(pMem, (DWORD)(pCurr - pMem));
(*pCodeFlowNode)->dwMemoryAddress = dwImageBase + dwRVA;
(*pCodeFlowNode)->pFileAddress = pCurr;
(*pCodeFlowNode)->dwType = JmpIns_Type_Jcc;
(*pCodeFlowNode)->pNext = NULL;
// 判断是否有前缀
if (ud_obj.pfx_opr == 0x66)
{
// 16位
(*pCodeFlowNode)->dwBits = Jmp_Bit_16;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
WORD wOffset = ud_obj.operand[0].lval.uword;
(*pCodeFlowNode)->wOffset = wOffset;
if (wOffset >= 0x8000)
{
(*pCodeFlowNode)->bGoDown = FALSE;
wOffset = ~wOffset;
wOffset++;
wOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - wOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
wOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + wOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
}
else
{
if (ud_obj.inp_sess[0] == 0x0F)
{
// 32位
(*pCodeFlowNode)->dwBits = Jmp_Bit_32;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
DWORD dwOffset = ud_obj.operand[0].lval.udword;
(*pCodeFlowNode)->dwOffset = dwOffset;
if (dwOffset >= 0x80000000)
{
(*pCodeFlowNode)->bGoDown = FALSE;
dwOffset = ~dwOffset;
dwOffset++;
dwOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - dwOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
dwOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + dwOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
}
else
{
// 8位
(*pCodeFlowNode)->dwBits = Jmp_Bit_8;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
BYTE bOffset = ud_obj.operand[0].lval.ubyte;
(*pCodeFlowNode)->bOffset = bOffset;
if (bOffset >= 0x80)
{
(*pCodeFlowNode)->bGoDown = FALSE;
bOffset = ~bOffset;
bOffset++;
bOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - bOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
bOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + bOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
}
}/* end else */
pCodeFlowNode = &((*pCodeFlowNode)->pNext);
}break;
case UD_Ijmp:
{
if (ud_obj.inp_sess[0] == 0xEB)
{
// 8位
// 分配节点内存
*pCodeFlowNode = new CODE_FLOW_NODE;
(*pCodeFlowNode)->bFar = FALSE;
DWORD dwRVA = PeDiy.Raw2Rva(pMem, (DWORD)(pCurr - pMem));
(*pCodeFlowNode)->dwMemoryAddress = dwImageBase + dwRVA;
(*pCodeFlowNode)->pFileAddress = pCurr;
(*pCodeFlowNode)->dwType = JmpIns_Type_Jmp;
(*pCodeFlowNode)->dwBits = Jmp_Bit_8;
(*pCodeFlowNode)->pNext = NULL;
BYTE bOffset = ud_obj.operand[0].lval.ubyte;
(*pCodeFlowNode)->bOffset = bOffset;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
if (bOffset >= 0x80)
{
(*pCodeFlowNode)->bGoDown = FALSE;
bOffset = ~bOffset;
bOffset++;
bOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - bOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
bOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + bOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
pCodeFlowNode = &((*pCodeFlowNode)->pNext);
}
else
{
if ((ud_obj.pfx_opr == 0x66) || (ud_obj.pfx_adr == 0x67))
{
if (ud_obj.inp_sess[1] == 0xE9)
{
// 16位
// 分配节点内存
*pCodeFlowNode = new CODE_FLOW_NODE;
(*pCodeFlowNode)->bFar = FALSE;
DWORD dwRVA = PeDiy.Raw2Rva(pMem, (DWORD)(pCurr - pMem));
(*pCodeFlowNode)->dwMemoryAddress = dwImageBase + dwRVA;
(*pCodeFlowNode)->pFileAddress = pCurr;
(*pCodeFlowNode)->dwType = JmpIns_Type_Jmp;
(*pCodeFlowNode)->dwBits = Jmp_Bit_16;
(*pCodeFlowNode)->pNext = NULL;
WORD wOffset = ud_obj.operand[0].lval.uword;
(*pCodeFlowNode)->wOffset = wOffset;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
if (wOffset >= 0x8000)
{
(*pCodeFlowNode)->bGoDown = FALSE;
wOffset = ~wOffset;
wOffset++;
wOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - wOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
wOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + wOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
pCodeFlowNode = &((*pCodeFlowNode)->pNext);
}/* end if */
}
else
{
if (ud_obj.inp_sess[0] == 0xE9)
{
// 32位
// 分配节点内存
*pCodeFlowNode = new CODE_FLOW_NODE;
(*pCodeFlowNode)->bFar = FALSE;
DWORD dwRVA = PeDiy.Raw2Rva(pMem, (DWORD)(pCurr - pMem));
(*pCodeFlowNode)->dwMemoryAddress = dwImageBase + dwRVA;
(*pCodeFlowNode)->pFileAddress = pCurr;
(*pCodeFlowNode)->dwBits = Jmp_Bit_32;
(*pCodeFlowNode)->dwType = JmpIns_Type_Jmp;
(*pCodeFlowNode)->pNext = NULL;
DWORD dwOffset = ud_obj.operand[0].lval.udword;
(*pCodeFlowNode)->dwOffset = dwOffset;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
if (dwOffset >= 0x80000000)
{
(*pCodeFlowNode)->bGoDown = FALSE;
dwOffset = ~dwOffset;
dwOffset++;
dwOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - dwOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
dwOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + dwOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
pCodeFlowNode = &((*pCodeFlowNode)->pNext);
}
}/* end else */
}/* end else */
}break;
case UD_Icall:
{
if ((ud_obj.pfx_opr == 0x66) || (ud_obj.pfx_adr == 0x67))
{
if (ud_obj.inp_sess[1] == 0xE8)
{
// 16位
// 分配节点内存
*pCodeFlowNode = new CODE_FLOW_NODE;
(*pCodeFlowNode)->bFar = FALSE;
DWORD dwRVA = PeDiy.Raw2Rva(pMem, (DWORD)(pCurr - pMem));
(*pCodeFlowNode)->dwMemoryAddress = dwImageBase + dwRVA;
(*pCodeFlowNode)->pFileAddress = pCurr;
(*pCodeFlowNode)->pNext = NULL;
(*pCodeFlowNode)->dwType = JmpIns_Type_Call;
(*pCodeFlowNode)->dwBits = Jmp_Bit_16;
WORD wOffset = ud_obj.operand[0].lval.uword;
(*pCodeFlowNode)->wOffset = wOffset;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
if (wOffset >= 0x8000)
{
(*pCodeFlowNode)->bGoDown = FALSE;
wOffset = ~wOffset;
wOffset++;
wOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - wOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
wOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + wOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
pCodeFlowNode = &((*pCodeFlowNode)->pNext);
}/* end if */
}
else
{
if (ud_obj.inp_sess[0] == 0xE8)
{
// 32位
// 分配节点内存
*pCodeFlowNode = new CODE_FLOW_NODE;
(*pCodeFlowNode)->bFar = FALSE;
DWORD dwRVA = PeDiy.Raw2Rva(pMem, (DWORD)(pCurr - pMem));
(*pCodeFlowNode)->dwMemoryAddress = dwImageBase + dwRVA;
(*pCodeFlowNode)->pFileAddress = pCurr;
(*pCodeFlowNode)->dwType = JmpIns_Type_Call;
(*pCodeFlowNode)->dwBits = Jmp_Bit_32;
(*pCodeFlowNode)->pNext = NULL;
DWORD dwOffset = ud_obj.operand[0].lval.udword;
(*pCodeFlowNode)->dwOffset = dwOffset;
(*pCodeFlowNode)->dwInsLen = ud_obj.inp_ctr;
if (dwOffset >= 0x80000000)
{
(*pCodeFlowNode)->bGoDown = FALSE;
dwOffset = ~dwOffset;
dwOffset++;
dwOffset -= ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress - dwOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}
else
{
(*pCodeFlowNode)->bGoDown = TRUE;
dwOffset += ud_obj.inp_ctr;
(*pCodeFlowNode)->dwGotoMemoryAddress = (*pCodeFlowNode)->dwMemoryAddress + dwOffset;
DWORD dwRaw = PeDiy.Rva2Raw(pMem, (DWORD)((*pCodeFlowNode)->dwGotoMemoryAddress - dwImageBase));
(*pCodeFlowNode)->pGotoFileAddress = pMem + dwRaw;
}/* end else */
pCodeFlowNode = &((*pCodeFlowNode)->pNext);
}/* end if */
}/* end else */
}break;
}/* end switch */
}/* end else */
pCurr += ud_obj.inp_ctr;
}/* end if */
pCodeFlow->pCodeFlow = pCodeFlowHeader;
return pCodeFlow;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!