int GetMinValidLenWithMatchOpcode ( LPBYTE OrgOpcode_Pb, int AtLeastLen_I) {//得到一个最少长为AtLeastLen_I的按opcode来的长度。 if (NULL==OrgOpcode_Pb) { return 0; } int RtnLen_I= 0; while (AtLeastLen_I>(RtnLen_I+= GetOpCodeSize ( OrgOpcode_Pb+ RtnLen_I))); return RtnLen_I; }
BOOL IsSystemCall(PVOID Routine) { PBYTE Buffer; Buffer = (PBYTE)Routine; if (Buffer[0] == 0xB8) return TRUE; for (ULONG_PTR Count = 1; Count != 0; --Count) { Buffer += GetOpCodeSize(Buffer); if (Buffer[0] == 0xB8) return TRUE; } return FALSE; }
HANDLE NTAPI QqCreateWaitQQProtectThread( PSECURITY_ATTRIBUTES ThreadAttributes, ULONG_PTR StackSize, PTHREAD_START_ROUTINE StartAddress, PVOID Parameter, ULONG CreationFlags, PULONG ThreadId ) { NTSTATUS Status; PVOID Ebp, CallCreateQQProtectExchangeWindow; PROCESS_BASIC_INFORMATION BasicInfo; LOOP_ONCE { if (PtrAnd(Parameter, 0xFFF00000) != 0) continue; Status = NtQueryInformationProcess((HANDLE)Parameter, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), nullptr); FAIL_BREAK(Status); if (BasicInfo.UniqueProcessId != CurrentPid()) break; AllocStack(16); Ebp = *((PVOID *)_AddressOfReturnAddress() - 1); CallCreateQQProtectExchangeWindow = *((PVOID *)Ebp + 1); if (*(PBYTE)CallCreateQQProtectExchangeWindow != CALL) break; NtClose((HANDLE)Parameter); *(PULONG_PTR)((PVOID *)Ebp + 1) += GetOpCodeSize(CallCreateQQProtectExchangeWindow); return nullptr; } return HummerCreateThread(ThreadAttributes, StackSize, StartAddress, Parameter, CreationFlags, ThreadId); }
DWORD X86RedirectOpcodeToNewBase (LPVOID NewBase, LPBYTE OrgOpcode, DWORD * LenOfOpcode_Dw, LPBYTE * Rtn_PPb) {//把一段opcode中的jcc和call受代码地址影响的code都处理成新地址的。返回的Rtn_PPb是需要用delete []删除的。 DWORD ValidOpcodeLen= GetMinValidLenWithMatchOpcode ( OrgOpcode, *LenOfOpcode_Dw); DWORD tempOpcodeOff_Dw= 0; DWORD PureJmpAddr_Dw= 0; LPBYTE RtnBuffer= new BYTE[*LenOfOpcode_Dw* 4];//全部都是jecxz也最多只会扩大4倍。 LPBYTE PtrIn_RtnBuffer= RtnBuffer; int tempForOpcodeLen= 0; int diffFromNewBaseAndRtnBuffer_I= (int)(RtnBuffer- (LPBYTE)NewBase); while (tempOpcodeOff_Dw<ValidOpcodeLen) { tempForOpcodeLen= GetOpCodeSize ( OrgOpcode+ tempOpcodeOff_Dw); switch (X86ShallToRedirect ( OrgOpcode+ tempOpcodeOff_Dw, OrgOpcode+ tempOpcodeOff_Dw, &PureJmpAddr_Dw, OrgOpcode, ValidOpcodeLen)) { case -1: //jcc的需要根据不同opcode来处理: switch ((OrgOpcode+ tempOpcodeOff_Dw)[0]) { case 0x0f: memcpy ( PtrIn_RtnBuffer, OrgOpcode+ tempOpcodeOff_Dw, 2); PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 2; *((PDWORD)(PtrIn_RtnBuffer))= PureJmpAddr_Dw- ((DWORD)PtrIn_RtnBuffer- 2- diffFromNewBaseAndRtnBuffer_I)- 6; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 4; break; case 0xe3: //这个很特殊,判断ecx的jecxz没有长跳转 //用 85 c9 test ecx, ecx // 0f 84 00000000 je addr来代替 PtrIn_RtnBuffer[0]= 0x85; PtrIn_RtnBuffer[1]= 0xc9; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 2; PtrIn_RtnBuffer[0]= 0x0f; PtrIn_RtnBuffer[1]= 0x84; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 2; *((PDWORD)(PtrIn_RtnBuffer))= PureJmpAddr_Dw- ((DWORD)PtrIn_RtnBuffer- 2- diffFromNewBaseAndRtnBuffer_I)- 6; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 4; break; default: //在default里也处理 0x7?的情况。 //这儿替换成对应的 0f 8? PtrIn_RtnBuffer[0]= 0x0f; PtrIn_RtnBuffer[1]= static_cast <BYTE> (0x80| (0xf& (OrgOpcode+ tempOpcodeOff_Dw)[0])); PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 2; *((PDWORD)(PtrIn_RtnBuffer))= PureJmpAddr_Dw- ((DWORD)PtrIn_RtnBuffer- 2- diffFromNewBaseAndRtnBuffer_I)- 6; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 4; break; case 0xeb: //*不能动orgopcode,其实只是改成0xeb,然后和jmp一样处理。*// // *PtrIn_RtnBuffer= 0xe9; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 1; *(DWORD *) (PtrIn_RtnBuffer)= PureJmpAddr_Dw- ((DWORD)PtrIn_RtnBuffer- 1- diffFromNewBaseAndRtnBuffer_I)- 5; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 4; break; case 0xe9: *PtrIn_RtnBuffer= *(OrgOpcode+ tempOpcodeOff_Dw); PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 1; *(DWORD *) (PtrIn_RtnBuffer)= PureJmpAddr_Dw- ((DWORD)PtrIn_RtnBuffer- 1- diffFromNewBaseAndRtnBuffer_I)- 5; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 4; //*32bits的jmp,可以和call那个一样处理*// // } break; case 1: //call的话,直接重新设置要跳转的地址就可以了。 *PtrIn_RtnBuffer= *(OrgOpcode+ tempOpcodeOff_Dw); PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 1; *(DWORD *) (PtrIn_RtnBuffer)= PureJmpAddr_Dw- ((DWORD)PtrIn_RtnBuffer- 1- diffFromNewBaseAndRtnBuffer_I)- 5; PtrIn_RtnBuffer= PtrIn_RtnBuffer+ 4; break; case 0: memcpy ( PtrIn_RtnBuffer, OrgOpcode+ tempOpcodeOff_Dw, tempForOpcodeLen); PtrIn_RtnBuffer= PtrIn_RtnBuffer+ tempForOpcodeLen; break; } tempOpcodeOff_Dw+= tempForOpcodeLen; } //tempOpcodeOff_Dw+= tempForOpcodeLen; *LenOfOpcode_Dw= tempOpcodeOff_Dw; *Rtn_PPb= RtnBuffer; return (DWORD)(PtrIn_RtnBuffer- RtnBuffer); }