ULONG GetThreadFlagsOffset() { UCHAR *cPtr, *pOpcode; ULONG Length; USHORT Offset; for (cPtr = (PUCHAR)PsTerminateSystemThread; cPtr < (PUCHAR)PsTerminateSystemThread + 0x100; cPtr += Length) { Length = SizeOfCode(cPtr, &pOpcode); if (!Length) break; if (*(USHORT *)pOpcode == 0x80F6) { Offset = *(USHORT *)((ULONG)pOpcode + 2); return Offset; } } return 0; }
LPVOID CreateBridge(LPVOID lpFunc,LPVOID lpBackup,SIZE_T *dwBackupCodeSize,ULONG_PTR *lpTable) { LPVOID lpBridge=MemAlloc(JUMP_SIZE*6); if (lpBridge) { DWORD dwOldProtect=0; VirtualProtect(lpBridge,JUMP_SIZE*6,PAGE_EXECUTE_READWRITE,&dwOldProtect); #ifdef _AMD64_ CALL_ABS call={0x15FF,0x00000000}; JMP_ABS jmp={0x25FF,0x00000000}; JCC_ABS jcc={0x70,0x02,0xEB,0x06,0x25FF,0x00000000}; int dwTmpAddrsCount=0; #else CALL_REL call={0xE8,0x00000000}; JMP_REL jmp={0xE9,0x00000000}; JCC_REL jcc={0x800F,0x00000000}; #endif TEMP_ADDR TmpAddr[MAX_JUMPS]={0}; int dwTmpAddrCount=0; SIZE_T dwOldPos=0,dwNewPos=0; ULONG_PTR dwJmpDest=0; bool bDone=false; while (!bDone) { hdes hs; LPVOID lpInst=(LPVOID)((ULONG_PTR)lpFunc+dwOldPos); SIZE_T dwCopySize=SizeOfCode(lpInst); if ((hs.flags & F_ERROR) == F_ERROR) break; LPVOID lpCopySrc=lpInst; if ((ULONG_PTR)lpInst-(ULONG_PTR)lpFunc >= sizeof(JMP_REL)) { LPVOID lpTmpAddr=0; #ifdef _AMD64_ lpTmpAddr=&lpTable[dwTmpAddrsCount++]; if (dwTmpAddrsCount > MAX_JUMPS) break; #endif AppendTempAddress(lpInst,dwNewPos,&jmp,&TmpAddr[dwTmpAddrCount++],(void **)lpTmpAddr); if (dwTmpAddrCount > MAX_JUMPS) break; lpCopySrc=&jmp; dwCopySize=sizeof(jmp); bDone=true; } #ifdef _AMD64_ else if ((hs.modrm & 0xC7) == 0x05) // RIP-based { AppendRipRelativeAddress(lpInst,dwNewPos,&hs,&TmpAddr[dwTmpAddrCount++]); if (dwTmpAddrCount > MAX_JUMPS) break; if ((hs.opcode == 0xFF) && (hs.modrm_reg == 4)) // jmp bDone=true; } #endif else if (hs.opcode == 0xE8) // call { LPVOID lpTmpAddr=0; #ifdef _AMD64_ lpTmpAddr=&lpTable[dwTmpAddrsCount++]; if (dwTmpAddrsCount > MAX_JUMPS) break; #endif AppendTempAddress(GetRelativeBranchDestination(lpInst,&hs),dwNewPos,&call,&TmpAddr[dwTmpAddrCount++],(void **)lpTmpAddr); if (dwTmpAddrCount > MAX_JUMPS) break; lpCopySrc=&call; dwCopySize=sizeof(call); } else if ((hs.opcode & 0xFD) == 0xE9) // jmp { LPVOID lpDest=GetRelativeBranchDestination(lpInst,&hs); if (IsInternalJump(lpFunc,(ULONG_PTR)lpDest)) dwJmpDest=max(dwJmpDest,(ULONG_PTR)lpDest); else { LPVOID lpTmpAddr=0; #ifdef _AMD64_ lpTmpAddr=&lpTable[dwTmpAddrsCount++]; if (dwTmpAddrsCount > MAX_JUMPS) break; #endif AppendTempAddress(lpDest,dwNewPos,&jmp,&TmpAddr[dwTmpAddrCount++],(void **)lpTmpAddr); if (dwTmpAddrCount > MAX_JUMPS) break; lpCopySrc = &jmp; dwCopySize = sizeof(jmp); bDone=((ULONG_PTR)lpInst >= dwJmpDest); } } else if (((hs.opcode & 0xF0) == 0x70) || (hs.opcode == 0xE3) || ((hs.opcode2 & 0xF0) == 0x80)) // jcc { LPVOID lpDest=GetRelativeBranchDestination(lpInst,&hs); if (IsInternalJump(lpFunc,(ULONG_PTR)lpDest)) dwJmpDest=max(dwJmpDest,(ULONG_PTR)lpDest); else if (hs.opcode == 0xE3) // jcxz, jecxz { bDone=false; break; } else { LPVOID lpTmpAddr=0; #ifdef _AMD64_ lpTmpAddr=&lpTable[dwTmpAddrsCount++]; if (dwTmpAddrsCount > MAX_JUMPS) break; #endif AppendTempAddress(lpDest,dwNewPos,&jcc,&TmpAddr[dwTmpAddrCount++],(void **)lpTmpAddr); if (dwTmpAddrCount > MAX_JUMPS) break; SetJccOpcode(&hs,&jcc); lpCopySrc=&jcc; dwCopySize=sizeof(jcc); } } else if (((hs.opcode & 0xFE) == 0xC2) || // ret ((hs.opcode & 0xFD) == 0xE9) || // jmp rel (((hs.modrm & 0xC7) == 0x05) && ((hs.opcode == 0xFF) && (hs.modrm_reg == 4))) || // jmp rip ((hs.opcode == 0xFF) && (hs.opcode2 == 0x25))) // jmp abs bDone=((ULONG_PTR)lpInst >= dwJmpDest); if (((ULONG_PTR)lpInst < dwJmpDest) && (dwCopySize != hs.len)) { bDone=false; break; } memcpy((byte*)lpBridge+dwNewPos,lpCopySrc,dwCopySize); dwOldPos+=hs.len; dwNewPos+=dwCopySize; } if (bDone) { memcpy(lpBackup,lpFunc,dwOldPos); *dwBackupCodeSize=dwOldPos; #ifdef _AMD64_ int dwAddrTblPos=0; #endif for (int i=0; i < dwTmpAddrCount; i++) { LPVOID lpAddr; #ifdef _AMD64_ if ((ULONG_PTR)TmpAddr[i].lpAddress < 0x10000) lpAddr=&lpTable[dwAddrTblPos++]; else #endif lpAddr=TmpAddr[i].lpAddress; byte *lpTrampoline=(byte*)lpBridge; *(DWORD*)(lpTrampoline+TmpAddr[i].dwPosition)=(DWORD)lpAddr-((DWORD)lpBridge+TmpAddr[i].dwPc); } return lpBridge; } else MemFree(lpBridge); } return NULL; }
//根据相同版本下与SSDT地址存在的偏移获取的SSDT SHADOW的地址 // WinDbg 下 ?KeServiceDescriptorTable- // 会打印出:Evaluate expression: 64 = 00000040(XP), -0xE0(2K) //卡巴斯基有个类似的函数:FindSystemServiceDescriptionTableShadow SYSTEM_SERVICE_TABLE *GetKeServiceDescriptorTableShadowX86() { //通过搜索 操作SSDT的函数实现中的有效内存地址的办法 来查找 Shadow SSDT // First, obtain a pointer to KeAddSystemServiceTable unsigned char *check = (unsigned char*)KeAddSystemServiceTable; int i; //Initialize an instance of System Service Table, will be used to //obtain an address from KeAddSystemServiceTable SYSTEM_SERVICE_TABLE *rc=0; KdPrint(("GetKeServiceDescriptorTableShadowX86, KeAddSystemServiceTable=%p\n", check)); // Make 100 attempts to match a valid address with that of KeServiceDescriptorTable for (i=0; i<4096; i++) { //PAGE_SIZE __try { // try to obtain an address from KeAddSystemServiceTable rc = *(SYSTEM_SERVICE_TABLE **)check; // if this address is NOT valid OR it itself is the address of //KeServiceDescriptorTable OR its first entry is NOT equal //to the first entry of KeServiceDescriptorTable if (!MmIsAddressValid (rc) || (rc == (SYSTEM_SERVICE_TABLE *)KeServiceDescriptorTable) || (memcmp (rc, KeServiceDescriptorTable, sizeof (*rc)) != 0)) { // Proceed with the next address check++; // don't forget to reset the old address rc = 0; } } __except (EXCEPTION_EXECUTE_HANDLER) { rc = 0; } // when the loop is completed, check if it produced a valid address if (rc) { // because if it didn't, we failed to find the address of KeServiceDescriptorTableShadow break; } } // otherwise, there is a valid address! So return it! return rc; //方法2 #if 0 PUCHAR cPtr, pOpcode; ULONG Length = 0; for (cPtr = (PUCHAR)KeAddSystemServiceTable; cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE; cPtr += Length) { if (!MmIsAddressValid(cPtr)) break; Length = SizeOfCode(cPtr, &pOpcode); if (!Length || (Length == 1 && *pOpcode == 0xC3)) break; //找到以下汇编对应的位置: //805ba5a3 8d8840a65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax] if (*(PUSHORT)pOpcode == 0x888D) { KeServiceDescriptorTableShadow = *(PVOID *)(pOpcode + 2); break; } } #endif }