问题描述
我想使用Intel PIN(主要是为了获取阵列写入信息)检测到mov dword ptr [rbp-0x28], 0x7
之类的指令(因此,所有mov dword ptr [rbp-0xxx], xxx
格式的指令).在未优化的代码中,这应该使大多数存储都存储到局部变量中.
I want to detect the instructions like mov dword ptr [rbp-0x28], 0x7
(so, all the instructions in mov dword ptr [rbp-0xxx], xxx
format) using Intel PIN (mainly to get array writes information). In un-optimized code, this should get most stores to local variables.
我可以做到:
if (INS_Opcode(ins) == XED_ICLASS_MOV)
instruction detection;
检测mov
指令.但是,与此同时,它还会检测其他指令,例如mov eax, 0x0
.我想用dword ptr
size指令检测指令.
to detect the mov
instruction. But, along with that it also detects other instruction such as mov eax, 0x0
. I want to detect the instructions with dword ptr
size directive.
我检查了引脚说明检查 API 并固定 xed-iclass-enum .使用该文档,我尝试过类似的操作:
I checked the pin instruction inspection API and pin xed-iclass-enum. Using that documentation I tried something like:
if ((INS_Opcode(ins) == XED_ICLASS_MOV) && INS_OperandIsMemory(ins, 0))
instruction detection;
这给了我想要的结果.但同时也给了我类似mov esi, eax
的说明(我不希望这样).
which gives me the desired result. But also gives me the instructions like mov esi, eax
(which I don't desire).
我的代码:
#include <fstream>
#include <iostream>
#include "pin.H"
#include <stack>
#include <unordered_map>
// Additional library calls go here
// Stack allocation
struct Node
{
int value;
};
std::stack<Node> mainStack;
// Ins object mapping
class Insr
{
private:
INS insobject;
public:
Insr(INS insob)
{
insobject = insob;
}
INS get_insobject()
{
return insobject;
}
};
static std::unordered_map<ADDRINT, Insr*> insstack;
// Output file object
ofstream OutFile;
//static uint64_t counter = 0;
std::string rtin = "";
// Make this lock if you want to print from _start
uint32_t key = 0;
void printmaindisas(uint64_t addr, std::string disassins)
{
std::stringstream tempstream;
tempstream << std::hex << addr;
std::string address = tempstream.str();
// if (addr > 0x700000000000)
// return;
if (addr > 0x700000000000)
return;
if (!key)
return;
// if (insstack[addr]->get_opcode() == XED_ICLASS_ADD || insstack[addr]->get_opcode()
// == XED_ICLASS_SUB)
INS ins = insstack[addr]->get_insobject();
if((INS_Opcode(ins) == XED_ICLASS_ADD || INS_Opcode(ins) == XED_ICLASS_SUB)
&&(INS_OperandIsImmediate(ins, 1)))
{
int value = INS_OperandImmediate(ins, 1);
std::cout << "value: " << value << '\n';
Node node{value};
mainStack.push(node);
std::cout << "stack top: " << mainStack.top().value << '\n';
}
if ((INS_Opcode(ins) == XED_ICLASS_MOV) && INS_OperandIsMemory(ins, 0))
{
std::cout << "yes!" << '\n';
}
std::cout<<address<<"\t"<<disassins<<std::endl;
}
void mutex_lock()
{
key = 0;
std::cout<<"out\n";
}
void mutex_unlock()
{
key = 1;
std::cout<<"in\n";
}
void Instruction(INS ins, VOID *v)
{
insstack.insert(std::make_pair(INS_Address(ins), new Insr(ins)));
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printmaindisas, IARG_ADDRINT, INS_Address(ins),
IARG_PTR, new string(INS_Disassemble(ins)), IARG_END);
}
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
// PIN_Init must be called before PIN_StartProgram
// as mentioned in the documentation
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);
// Add an isntruction instrumentation
INS_AddInstrumentFunction(Instruction, 0);
//PIN_AddFiniFunction(Fini, 0);
// Start the program here
PIN_StartProgram();
return 0;
}
我得到的输出是
in
40051e push rbp
value: -128
stack top: -128
40051f mov rbp, rsp
400522 add rsp, 0xffffffffffffff80
yes!
400526 mov dword ptr [rbp-0x28], 0x7
yes!
40052d mov dword ptr [rbp-0x64], 0x9
400534 mov eax, 0x0
400539 call 0x4004e6
4004e6 push rbp
value: 64
stack top: 64
4004e7 mov rbp, rsp
4004ea sub rsp, 0x40
yes!
4004ee mov dword ptr [rbp-0xc], 0x4
4004f5 lea rax, ptr [rbp-0xc]
yes!
4004f9 mov qword ptr [rbp-0x8], rax
4004fd mov rax, qword ptr [rbp-0x8]
400501 mov eax, dword ptr [rax]
yes!
400503 mov esi, eax
400505 mov edi, 0x4005d0
40050a mov eax, 0x0
40050f 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]
4
yes!
400514 mov dword ptr [rbp-0x3c], 0x3
40051b nop
40051c leave
40051d ret
40053e mov eax, 0x0
400543 leave
out
这是正确的方法(没有任何误报)吗?
Is this the correct way to do that (without any false positives)?
推荐答案
如果您要接受以下所有说明:
If you want to accept all of the following instructions:
mov [rbp + disp], reg/imm
mov [rbp*scale + disp], reg/imm
mov [reg + rbp*scale], reg/imm
mov [rbp + reg*scale + disp], reg/imm
然后您需要执行以下检查:
then you need to perform the following checks:
if (INS_Opcode(ins) == XED_ICLASS_MOV && // Check that the instruction is MOV.
INS_OperandIsMemory(ins, 0) && // Check that the destination operand is a memory operand.
INS_OperandWidth(ins, 0) == 32 && // Check that the size of the operand is 32 bits.
(INS_OperandMemoryBaseReg(ins, 0) == REG_EBP ||
INS_OperandMemoryIndexReg(ins, 0) == REG_EBP)) // Check that the base or index register is RBP.
{
...
}
请注意,这些检查既接受带位移的MOV指令(包括位移为零),也接受不带位移的MOV指令(语义上等同于位移为零,但编码不同).
Note that these checks accept both MOV instructions with displacement (including a displacement of zero) and MOV instructions without displacement (which is semantically equivalent to a displacement of zero but the encoding is different).
我假设您想同时接受RBP作为基址寄存器或索引寄存器(可能具有大于1的小数位数).请注意,如果将RBP用作基址寄存器,则指令的编码将始终包含位移.请参阅:为什么rbp和rsp称为通用寄存器?.
I assumed that you want to accept RBP both as a base register or as an index register (potentially with a scale larger than 1). Note that in case RBP is used as a base register, the encoding of the instruction will always include a displacement. See: Why are rbp and rsp called general purpose registers?.
如果要接受以下所有说明,其中将RBP
用作基本寄存器:
If you want to accept all of the following instructions where RBP
is used as the base register:
mov [rbp + disp], reg/imm
mov [rbp + reg*scale + disp], reg/imm
然后您需要执行以下检查:
then you need to perform the following checks:
if (INS_Opcode(ins) == XED_ICLASS_MOV && // Check that the instruction is MOV.
INS_OperandIsMemory(ins, 0) && // Check that the destination operand is a memory operand.
INS_OperandWidth(ins, 0) == 32 && // Check that the size of the operand is 32 bits.
INS_OperandMemoryBaseReg(ins, 0) == REG_EBP) // Check that the base is RBP.
{
...
}
如果您只想接受以下说明:
If you want to accept only the following instruction:
mov [rbp + disp], reg/imm
然后您需要执行以下检查:
then you need to perform the following checks:
if (INS_Opcode(ins) == XED_ICLASS_MOV && // Check that the instruction is MOV.
INS_OperandIsMemory(ins, 0) && // Check that the destination operand is a memory operand.
INS_OperandWidth(ins, 0) == 32 && // Check that the size of the operand is 32 bits.
INS_OperandMemoryBaseReg(ins, 0) == REG_EBP && // Check that the base is RBP.
INS_OperandMemoryIndexReg(ins, 0) == REG_INVALID()) // Check that there is no index register.
{
...
}
如果要检查位移是否为负数,请使用以下检查:
If you want to check whether the displacement is a negative number, use the following check:
INS_OperandMemoryDisplacement(ins, 0) < 0
请注意,INS_OperandMemoryDisplacement
不能区分没有位移的存储操作数和位移为零的存储操作数.如果没有位移,则仅返回零.如果要确定指令编码是否实际上包含位移字段,则应改用XED API.
Note that INS_OperandMemoryDisplacement
does not distinguish between a memory operand that has no displacement and one that has a displacement of zero. If there is no displacement, it just returns zero. If you want to determine whether the instruction encoding actually includes a displacement field, then you should use the XED API instead.
这篇关于使用英特尔PIN在寻址模式下使用特定寄存器检测mov dword ptr [rbp-...]指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!