static VOID After1WithContext (ADDRINT ip, ADDRINT repInsAddr, CONTEXT * ctxt, CONTEXT *constCtxt, ADDRINT *constRefToIp ) { ADDRINT expectedIpAfter; numCallsToAfter1WithContext++; printf ("***After1WithContext# %d repInsAddr %p ip %p\n",//*constRefToIp %p\n", numCallsToAfter1WithContext, (char *)repInsAddr, (char *)ip //,(char *)constRefToIp, //(char *)(*constRefToIp) ); if (numCallsToAfter1WithContext == 2) { // see "Test different string comparison" in rep_ip_at_ipoint_after_app.c expectedIpAfter = repInsAddr+GetInstructionLength(repInsAddr); } else { expectedIpAfter = repInsAddr; } if (ip != *constRefToIp) { printf ("Unexpcted diff between ip and *constRefToIp\n"); exit (1); } if (PIN_GetContextReg( ctxt, REG_INST_PTR )!=expectedIpAfter) { printf (" After1WithContext Unexpected IP in ctxt %p\n", (char *)PIN_GetContextReg( ctxt, REG_INST_PTR )); exit (1); } if (PIN_GetContextReg( constCtxt, REG_INST_PTR )!=expectedIpAfter) { printf (" After1WithContext Unexpected IP in constCtxt %p\n", (char *)PIN_GetContextReg( constCtxt, REG_INST_PTR )); exit (1); } if (expectedIpAfter!=ip) { printf (" After1WithContext Unexpected IP from REG_VALUE REG_INST_PTR %p\n", (char *)ip); exit (1); } }
/** --------------------------------------------------------------------------- \brief [target function] A1 A2 (A1 + RealPatchSize) |-----jmp A3 -- x90x90 --|^------------- ( RealPatchSize ) jmp A3 ===> A4 ( OpenProcess_Detour() 함수 주소 ) A4 = A2 + A3 이므로 (jmp 명령이니까) A3 = A4 - A2 [trampoline] T1 T2 T3 T4 |-----MAX_PATCH_SIZE-----|jmp|-----4----| jmp T3 ===> A2 A2 = T4 + T3 이므로 T3 = A2 - T4 \param \return \code \endcode -----------------------------------------------------------------------------*/ int InjectDetour(TD_HOOK_INFO* pHookInfo) { _ASSERTE(NULL != pHookInfo); _ASSERTE(NULL != pHookInfo->Target); _ASSERTE(NULL != pHookInfo->Detour); _ASSERTE(NULL != pHookInfo->Trampoline); if ((NULL == pHookInfo) || (NULL == pHookInfo->Target) || (NULL == pHookInfo->Detour) || (NULL == pHookInfo->Trampoline) ) { return -1; } //------------------------------------------------------------------------- // # STEP 1 // build trampoline //------------------------------------------------------------------------- // [TargetFunc's original opcode] [jmp] [TagetFunc + 5] // // trampoline 에 TargetFunc 의 코드를 복사해 둔다. // - TargetFunc 에 JMP_REL_32_SIZE 만큼의 명령어 공간을 계산 // int Len = 0; DWORD dwOpcodeLen = 0; do { Len = GetInstructionLength(pHookInfo->Target + dwOpcodeLen); if (-1 == Len) { _ASSERTE(!"GetInstructionLength"); return -1; } dwOpcodeLen += Len; } while (JMP_REL_32_SIZE > dwOpcodeLen); pHookInfo->OriginalOpcodeLen = dwOpcodeLen; #ifdef _DEBUG _tprintf(TEXT("target instruction length: %ld\n"), pHookInfo->OriginalOpcodeLen); #endif if (MAX_PATCH_SIZE < pHookInfo->OriginalOpcodeLen) { _ASSERTE(!"too big patch size"); return -1; } if (0 != CopyCodeBytes(pHookInfo->Target, pHookInfo->Trampoline, pHookInfo->OriginalOpcodeLen)) { _ASSERTE(!"CopycodeBytes"); return -1; } pHookInfo->Trampoline[MAX_PATCH_SIZE] = INST_JMP; DWORD_PTR tp_jmp = (pHookInfo->Target + pHookInfo->OriginalOpcodeLen) - (pHookInfo->Trampoline + MAX_PATCH_SIZE + JMP_REL_32_SIZE); *(DWORD_PTR*)(&pHookInfo->Trampoline[MAX_PATCH_SIZE + INST_JMP_SIZE]) = tp_jmp; //------------------------------------------------------------------------- // # STEP 2 // build jmp [detour] stub // reroute TargetFunc to DetourFunc //------------------------------------------------------------------------- // bto (buffer to overwite) = jmp [DetourFunc] // BYTE* bto = (BYTE*) malloc(pHookInfo->OriginalOpcodeLen); // RealPatchSize 에서 jmp rel_32 명령을 제외한 나머지 부분은 nop 처리 // memset(bto, 0x90, pHookInfo->OriginalOpcodeLen); bto[0] = INST_JMP; *(reinterpret_cast<DWORD_PTR*>(bto + 1)) = pHookInfo->Detour - (pHookInfo->Target + JMP_REL_32_SIZE); if (0 != CopyCodeBytes(bto, pHookInfo->Target, pHookInfo->OriginalOpcodeLen)) { _ASSERTE(!"CopycodeBytes"); if (NULL != bto){ free(bto); bto = NULL; } return -1; } if (NULL != bto){ free(bto); bto = NULL; } pHookInfo->Enabled = TRUE; return 0; }