[英]add your own instructions using pin
intel-pin生成的代碼中可以添加自己的代碼嗎?
我想了一會兒,我創建了一個簡單的工具:
#include <fstream>
#include <iostream>
#include "pin.H"
// Additional library calls go here
/*********************/
// Output file object
ofstream OutFile;
//static uint64_t counter = 0;
uint32_t lock = 0;
uint32_t unlock = 1;
std::string rtin = "";
// Make this lock if you want to print from _start
uint32_t key = unlock;
void printmaindisas(uint64_t addr, std::string disassins)
{
std::stringstream tempstream;
tempstream << std::hex << addr;
std::string address = tempstream.str();
if (key)
return;
if (addr > 0x700000000000)
return;
std::cout<<address<<"\t"<<disassins<<std::endl;
}
void mutex_lock()
{
key = !lock;
std::cout<<"out\n";
}
void mutex_unlock()
{
key = lock;
std::cout<<"in\n";
}
void Instruction(INS ins, VOID *v)
{
//if
// Insert a call to docount before every instruction, no arguments are passed
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printmaindisas, IARG_ADDRINT, INS_Address(ins),
IARG_PTR, new string(INS_Disassemble(ins)), IARG_END);
//std::cout<<INS_Disassemble(ins)<<std::endl;
}
void Routine(RTN rtn, VOID *V)
{
if (RTN_Name(rtn) == "main")
{
//std::cout<<"Loading: "<<RTN_Name(rtn) << endl;
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mutex_unlock, IARG_END);
RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)mutex_lock, IARG_END);
RTN_Close(rtn);
}
}
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "mytool.out", "specify output file name");
/*
VOID Fini(INT32 code, VOID *v)
{
// Write to a file since cout and cerr maybe closed by the application
OutFile.setf(ios::showbase);
OutFile << "Count " << count << endl;
OutFile.close();
}
*/
int32_t Usage()
{
cerr << "This is my custom tool" << endl;
cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
return -1;
}
int main(int argc, char * argv[])
{
// It must be called for image instrumentation
// Initialize the symbol table
PIN_InitSymbols();
// Initialize pin
if (PIN_Init(argc, argv)) return Usage();
// Open the output file to write
OutFile.open(KnobOutputFile.Value().c_str());
// Set instruction format as intel
// Not needed because my machine is intel
//PIN_SetSyntaxIntel();
RTN_AddInstrumentFunction(Routine, 0);
//IMG_AddInstrumentFunction(Image, 0);
// Add an isntruction instrumentation
INS_AddInstrumentFunction(Instruction, 0);
//PIN_AddFiniFunction(Fini, 0);
// Start the program here
PIN_StartProgram();
return 0;
}
如果我打印以下 c 代碼(實際上什么都不做):
int main(void)
{}
給我這個輸出:
in
400496 push rbp
400497 mov rbp, rsp
40049a mov eax, 0x0
40049f pop rbp
out
並使用以下代碼:
#include <stdio.h>
int main(void)
{
printf("%s\n", "Hello");
}
印刷:
in
4004e6 push rbp
4004e7 mov rbp, rsp
4004ea mov edi, 0x400580
4004ef call 0x4003f0
4003f0 jmp qword ptr [rip+0x200c22]
4003f6 push 0x0
4003fb jmp 0x4003e0
4003e0 push qword ptr [rip+0x200c22]
4003e6 jmp qword ptr [rip+0x200c24]
Hello
4004f4 mov eax, 0x0
4004f9 pop rbp
out
所以,我的問題是,是否可以添加:
4004ea mov edi, 0x400580
4004ef call 0x4003f0
4003f0 jmp qword ptr [rip+0x200c22]
4003f6 push 0x0
4003fb jmp 0x4003e0
4003e0 push qword ptr [rip+0x200c22]
4003e6 jmp qword ptr [rip+0x200c24]
我的第一個代碼(沒有打印功能的代碼)中的指令,在儀器例程/或分析例程中使用 pin,以便我可以模仿我的第二個代碼(通過動態添加這些指令)? (我不想直接調用printf
,而是想模仿這種行為)(將來我正在考慮使用 pin 模仿健全性檢查器或 intel mpx,如果我可以以某種方式動態添加這些檢查指令)
我看了pin文檔,有指令修改api ,但是只能用於添加直接/間接分支或刪除指令(但我們不能添加添加新指令)。
請你幫助我好嗎? 我還要提前感謝您調查這個問題。
分析例程(或替換例程)實際上只是插入到正在分析的應用程序中的代碼。 但在我看來,您想要修改應用程序上下文的一個或多個寄存器。 默認情況下,當分析例程執行時,Pin 運行時在分析例程的入口處保存應用程序上下文,然后在例程返回時恢復它。 這基本上允許執行分析例程而不會對應用程序進行任何意外更改。 但是,Pin 提供了三種方法來在分析或替換例程中修改應用程序上下文:
IARG_RETURN_REGS
參數傳遞給例程。 從例程返回的值存儲到應用程序上下文的指定寄存器中。 這使您能夠更改大小不超過ADDRINT
大小的任何單個寄存器,這是例程的返回值類型。 這在探測模式或緩沖 API 1 中不受支持。 但是,這是更改單個寄存器的最有效方法。IARG_REG_REFERENCE
參數。 對於每個這樣的參數,您需要在PIN_REGISTER*
類型的例程的聲明中添加一個參數。 這在探測模式或緩沖 API 中不受支持,但它是更改幾個寄存器並支持所有寄存器的最有效方法。IARG_CONTEXT
參數傳遞給例程。 您需要在類型為CONTEXT*
的例程的聲明中添加一個參數。 使用上下文操作 API 來更改應用程序上下文的一個或多個寄存器。 例如,您可以使用PIN_SetContextReg(ctxt, REG_INST_PTR, NewRipValue)
更改應用程序上下文的RIP
寄存器。 為了使上下文更改生效,必須調用PIN_ExecuteAt
,它會在具有指定上下文的潛在更改的RIP
上恢復應用程序的執行。 Buffering API 不支持此功能,並且在 Probe 模式中存在限制。 例如,如果您想在應用程序上下文中執行mov edi, 0x400580
,您可以在分析例程中簡單地將值0x400580
存儲在應用程序上下文的EDI
寄存器中:
r->dword[0] = 0x400580;
r->dword[1] = 0x0; // See: https://stackoverflow.com/questions/11177137/why-do-x86-64-instructions-on-32-bit-registers-zero-the-upper-part-of-the-full-6
其中r
的類型為PIN_REGISTER*
。 或者:
PIN_SetContextReg(ctxt, REG_EDI, 0x400580); // https://stackoverflow.com/questions/38782709/what-is-the-default-type-of-integral-literals-represented-in-hex-or-octal-in-c
稍后當應用程序執行恢復時, RDI
將包含 0x400580。
請注意,您可以更改分析例程中的任何有效內存位置,無論它屬於應用程序還是您的 Pin 工具。 例如,如果應用程序上下文的RAX
寄存器包含一個指針,您可以像訪問任何其他指針一樣直接訪問該指針處的內存位置。
腳注:
(1) 您似乎沒有使用探測模式或緩沖 API。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.