taint analysis
- DBI - pin & pintool 2017.05.22 4
DBI - pin & pintool
PIN 에 대해서 공부한지는 조금 되었으나 적당히 기존 코드로만 붙여넣기 해서 사용했던 것이 사실이다. 최근 개인 프로젝트로 PIN 을 사용할 일이 생겨서 하는 김에 정리해 둔다.
PIN
PIN 이란, Intel 에서 제작 및 관리중인 Dynamic Binary Instrumentation Framework 이다. BI 분야에서 실행을 하지 않고 조사하는 SBI 와 동적으로 실행중 코드를 조사하는 DBI 가 있는데, 그 중 PIN 은 DBI 를 위한 SDK(?) 정도로 볼 수 있다.
Intel 이란 기업에서 관리하기 때문에 상당히 업데이트가 잘 되고 있으며 매뉴얼도 매우 충실하게 잘 되어 있다. 또한 수많은 예제코드가 들어 있어서 몇개의 코드만 분석해 보면 바로 사용방법을 알 수 있을 정도로 완성도가 높다.
한가지 단점은 C++ 로 작성해서 DLL 로 컴파일 해야 하므로 스크립트 언어에 비해 수정&적용이 조금 오래 걸린다는 점이 있다. 하지만 이러한 단점은 장점에 비해 크지 않으므로 수년전부터 현재까지도 PIN 은 매우 인기 있는 DBI 프레임워크로 자리잡았다.
PIN 은 그 자체로 pin.exe 로 독립된 바이너리이며, 실행 파일을 에뮬레이션 해준다. 에뮬레이션 하는 동안 PINTOOL 로 작성한 DLL 코드를 통해 다양하게 동적으로 코드를 수행할 수 있다.
PINTOOL
PINTOOL 은 PIN SDK 를 이용하여 개발한 라이브러리이다. pin.exe 실행 시 옵션으로(-t) 지정해주면 해당 PINTOOL 을 이용하여 타겟 바이너리를 실행시켜 준다.
Build PINTOOL
다운로드 및 설치는 검색하면 많으니 타 자료를 참고바란다. 여러가지 방법이 있지만 개인적으로는 cygwin + make 가 편한 듯 하다. visual studio 로도 가능하지만 컴파일 프로그램 특성상 소스코드 수정, 컴파일 및 실행, 빌드된 파일 이동, 실행 등을 자주 해야 해서 차라리 make 로 배치 파일을 만드는 것이 편하다.
# make.bat
cd C:\Users\hyunmini\Desktop\pin-3.2-81205-msvc-windows\source\tools\MyPinTool
make
copy /y obj-ia32\MyPinTool.dll c:\Users\FSI\Desktop\dbi\pin
cd c:\Users\hyunmini\Desktop\dbi\pin
Simple Example 1 - call tracer
#include "pin.H" #include <asm/unistd.h> #include <iostream> #include <fstream> #include <list> UINT32 insCount = 0; UINT32 bblCount = 0; UINT32 threadCount = 0; UINT32 traceCount = 0; std::ostream * out = &cerr; KNOB<string> KnobTraceString(KNOB_MODE_WRITEONCE, "pintool", "s", "", "trace string"); INT32 Usage() { cerr << "This tool prints out the traced call with arguments." << endl; cerr << KNOB_BASE::StringKnobSummary() << endl; return -1; } string invalid = "invalid_rtn"; const string *Target2String(ADDRINT target) { string name = RTN_FindNameByAddress(target); if (name == "") { return &invalid; } else if (name == ".text" || name == "unnamedImageEntryPoint") { return new string(StringFromAddrint(target)); } else return new string(name); } string ReadCString(ADDRINT target){ ADDRINT Buffer; PIN_SafeCopy(&Buffer, (ADDRINT *)(target), sizeof(ADDRINT)); string cstring; while (1) { char c = 0; if (PIN_SafeCopy(&c, (ADDRINT *) Buffer, 1) != 1) break; if (c == 0) break; cstring += c; Buffer += 1; } return cstring; } VOID do_call_args(ADDRINT ins,const string *s, ADDRINT arg0, ADDRINT arg1, ADDRINT arg2, ADDRINT esp) { PIN_LockClient(); string img_name = IMG_Name(IMG_FindByAddress(ins)); PIN_UnlockClient(); string base_img_name = img_name.substr(img_name.find_last_of("/\\") + 1); string argstr1 = ReadCString(esp); string argstr2 = ReadCString(esp+4); string argstr3 = ReadCString(esp+8); if( argstr1.find(KnobTraceString.Value()) != string::npos || argstr2.find(KnobTraceString.Value()) != string::npos || argstr3.find(KnobTraceString.Value()) != string::npos ){ *out << StringFromAddrint(ins) << " : " << base_img_name << "!" << *s << "(0x" << std::hex << arg0 << ", 0x" << arg1 << ", 0x" << arg2 << "...)" << endl; if(argstr1.length()>10){ argstr1 = argstr1.substr(0,10); argstr1 += "..."; } if(argstr2.length()>10){ argstr2 = argstr2.substr(0,10); argstr2 += "..."; } if(argstr3.length()>10){ argstr3 = argstr3.substr(0,10); argstr3 += "..."; } *out << " arg1 : " << argstr1 << endl; *out << " arg2 : " << argstr2 << endl; *out << " arg3 : " << argstr3 << endl; } } VOID do_call_args_indirect(ADDRINT ins, ADDRINT target, BOOL taken, ADDRINT arg0, ADDRINT arg1, ADDRINT arg2, ADDRINT esp) { if( !taken ) return; const string *s = Target2String(target); do_call_args(ins, s, arg0, arg1, arg2, esp); if (s != &invalid) delete s; } /* ===================================================================== */ VOID Trace(TRACE trace, VOID *v) { PIN_LockClient(); IMG img = IMG_FindByAddress(TRACE_Address(trace)); PIN_UnlockClient(); if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); if( INS_IsCall(tail) ) { if( INS_IsDirectBranchOrCall(tail) ) { // direct call const ADDRINT target = INS_DirectBranchOrCallTargetAddress(tail); INS_InsertPredicatedCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args), IARG_INST_PTR, IARG_PTR, Target2String(target), IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_REG_VALUE, REG_ESP, IARG_END); } else { // indirect call INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_REG_VALUE, REG_ESP, IARG_END); } } else { RTN rtn = TRACE_Rtn(trace); if( RTN_Valid(rtn) && !INS_IsDirectBranchOrCall(tail)) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_REG_VALUE, REG_ESP, IARG_END); } } } } } int main(int argc, char *argv[]) { PIN_InitSymbols(); if( PIN_Init(argc,argv) ){ return Usage(); } string fileName = "trace_result.txt"; if (!fileName.empty()) { out = new std::ofstream(fileName.c_str());} TRACE_AddInstrumentFunction(Trace, 0); PIN_StartProgram(); return 0; }
실행결과
x00489d99 : VUPlayer.exe!_mbscmp(0x3c34f3c, 0x3be35f8, 0x74aeac8...) arg1 : AAAAAAAAAA... arg2 : #VUPlayer ... arg3 : 0x004552ac : VUPlayer.exe!_mbsicmp(0x3c3408c, 0x51f140, 0x0...) arg1 : AAAAAAAAAA... arg2 : mod arg3 : 0x004552d2 : VUPlayer.exe!_mbsicmp(0x3c3408c, 0x51f13c, 0x0...) arg1 : AAAAAAAAAA... arg2 : s3m arg3 : 0x004552f8 : VUPlayer.exe!_mbsicmp(0x3c3408c, 0x51f138, 0x0...) arg1 : AAAAAAAAAA... arg2 : xm arg3 : 0x00456191 : VUPlayer.exe!fopen(0x3c3408c, 0x51e098, 0x12d198...) arg1 : AAAAAAAAAA... arg2 : rb arg3 : dœP 0x004562a3 : VUPlayer.exe!0x004b9f68(0x0, 0x3c3408c, 0x0...) arg1 : arg2 : AAAAAAAAAA... arg3 : 0x004b9f68 : VUPlayer.exe!BASS_MusicLoad(0x4562a8, 0x0, 0x3c3408c...) arg1 : ‰Eüƒ}ü arg2 : arg3 : AAAAAAAAAA... 0x00456191 : VUPlayer.exe!fopen(0x3c3408c, 0x51e098, 0x12d198...) arg1 : AAAAAAAAAA... arg2 : rb arg3 : dœP 0x00456191 : VUPlayer.exe!fopen(0x3c3408c, 0x51e098, 0x12d198...) arg1 : AAAAAAAAAA... arg2 : rb arg3 : dœP 0x00453313 : VUPlayer.exe!lstrcpyA(0x12cc44, 0x3c3408c, 0x12d3a8...) arg1 : arg2 : AAAAAAAAAA... arg3 : 0ü¿4P 0x00453325 : VUPlayer.exe!fopen(0x12cc44, 0x51e098, 0x12d3a8...) arg1 : AAAAAAAAAA... arg2 : rb arg3 : AAAAAAAAAA...
Taint Analysis with PIN
taint analysis 는 이론부터 설명하면 매우 길기 때문에 더이상의 설명은 생략한다!(...)
결론은 쓸만하지만 오류 없이 쓰려면 훨~씬 세세한 컨트롤을 해줘야 함. 그러므로 여기까지만..
* 코드 일부 생략.
** (http://shell-storm.org/blog/Taint-analysis-and-pattern-matching-with-Pin 코드를 아주 많이 참고 하였음을 밝힙니다)
#include "pin.H"
#include <asm/unistd.h> #include <iostream> #include <fstream> #include <list> UINT32 insCount = 0; UINT32 bblCount = 0; UINT32 threadCount = 0; UINT32 traceCount = 0; BOOL start_taint = false; std::ostream * out = &cerr; std::list<ADDRINT> addressTainted; std::list<REG> regsTainted; string invalid = "invalid_rtn"; //////////////////////// // trace user input // //////////////////////// VOID fgetsBefore(ADDRINT arg0, ADDRINT arg1, ADDRINT arg2) { *out << "[Taint] fgets() : " << endl; *out << " buf : 0x" << std::hex << arg1 << endl; *out << " size : 0x" << arg2 << endl; int size = static_cast<ADDRINT>(arg2); start_taint = true; for (int i=0;i<size;i++){ addressTainted.push_back(arg1+i); } } VOID recvBefore(ADDRINT arg0, ADDRINT arg1, ADDRINT arg2, ADDRINT arg3) { *out << "[Taint] recv() : " << endl; *out << " buf : 0x" << std::hex << arg2 << endl; *out << " size : 0x" << arg3 << endl; int size = static_cast<ADDRINT>(arg3); start_taint = true; for (int i=0;i<size;i++){ addressTainted.push_back(arg2+i); } } /////////////////////// /// taint analysis /// /////////////////////// bool IsRegTainted(REG reg){ list<REG>::iterator i; for(i = regsTainted.begin(); i != regsTainted.end(); i++){ if (*i == reg){ return true; } } return false; } bool IsMemTainted(ADDRINT mem){ list<ADDRINT>::iterator i; for(i = addressTainted.begin(); i != addressTainted.end(); i++){ if (mem == *i){ return true; } } return false; } bool removeRegTainted(REG reg){ switch(reg){ case REG_EAX: regsTainted.remove(REG_EAX); case REG_AX: regsTainted.remove(REG_AX); case REG_AH: regsTainted.remove(REG_AH); case REG_AL: regsTainted.remove(REG_AL); break; case REG_EBX: regsTainted.remove(REG_EBX); case REG_BX: regsTainted.remove(REG_BX); case REG_BH: regsTainted.remove(REG_BH); case REG_BL: regsTainted.remove(REG_BL); break; case REG_ECX: regsTainted.remove(REG_ECX); case REG_CX: regsTainted.remove(REG_CX); case REG_CH: regsTainted.remove(REG_CH); case REG_CL: regsTainted.remove(REG_CL); break; case REG_EDX: regsTainted.remove(REG_EDX); case REG_DX: regsTainted.remove(REG_DX); case REG_DH: regsTainted.remove(REG_DH); case REG_DL: regsTainted.remove(REG_DL); break; case REG_EDI: regsTainted.remove(REG_EDI); case REG_DI: regsTainted.remove(REG_DI); break; case REG_ESI: regsTainted.remove(REG_ESI); case REG_SI: regsTainted.remove(REG_SI); break; default: return false; } *out << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; return true; } bool taintReg(REG reg){ if (IsRegTainted(reg)){ * out << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; return false; } switch(reg){ case REG_EAX: regsTainted.push_front(REG_EAX); case REG_AX: regsTainted.push_front(REG_AX); case REG_AH: regsTainted.push_front(REG_AH); case REG_AL: regsTainted.push_front(REG_AL); break; case REG_EBX: regsTainted.push_front(REG_EBX); case REG_BX: regsTainted.push_front(REG_BX); case REG_BH: regsTainted.push_front(REG_BH); case REG_BL: regsTainted.push_front(REG_BL); break; case REG_ECX: regsTainted.push_front(REG_ECX); case REG_CX: regsTainted.push_front(REG_CX); case REG_CH: regsTainted.push_front(REG_CH); case REG_CL: regsTainted.push_front(REG_CL); break; case REG_EDX: regsTainted.push_front(REG_EDX); case REG_DX: regsTainted.push_front(REG_DX); case REG_DH: regsTainted.push_front(REG_DH); case REG_DL: regsTainted.push_front(REG_DL); break; case REG_EDI: regsTainted.push_front(REG_EDI); case REG_DI: regsTainted.push_front(REG_DI); break; case REG_ESI: regsTainted.push_front(REG_ESI); case REG_SI: regsTainted.push_front(REG_SI); break; default: *out << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; return false; } *out << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; return true; } VOID ReadMem(INS ins, ADDRINT memOp){ // memory -> reg list<ADDRINT>::iterator i; ADDRINT addr = memOp; REG read_reg; if (INS_OperandCount(ins) != 2) return; read_reg = INS_OperandReg(ins, 0); for(i = addressTainted.begin(); i != addressTainted.end(); i++){ if (addr == *i){ // tainted memory > register *out << "[Read][0x" << std::hex << INS_Address(ins) <<"] : " << INS_Disassemble(ins) << endl; taintReg(read_reg); return ; } } if (IsRegTainted(read_reg)){ // untainted memory > tainted register => clear reg *out << "[Read][0x" << std::hex << INS_Address(ins) <<"] : " << INS_Disassemble(ins) << endl; removeRegTainted(read_reg); } } VOID WriteMem(INS ins, ADDRINT memOp){ // reg -> memory list<ADDRINT>::iterator i; ADDRINT addr = memOp; REG read_reg; if (INS_OperandCount(ins) != 2) return; read_reg = INS_OperandReg(ins, 1); for(i = addressTainted.begin(); i != addressTainted.end(); i++){ if (addr == *i){ // tainted memory *out << "[Write][0x" << std::hex << INS_Address(ins) <<"] : " << INS_Disassemble(ins) << endl; if (!REG_valid(read_reg) || !IsRegTainted(read_reg)){ // untainted register > tainted memory => clear memory addressTainted.remove(addr); } *out << std::hex << "\t\t\t0x" << addr << " is now freed" << std::endl; return; } } if (IsRegTainted(read_reg)) { // tainted reg > untainted memory => tainted addressTainted.push_back(addr); *out << std::hex << "\t\t\t0x" << addr << " is now tainted" << std::endl; return; } } VOID spreadReg(INS ins) { REG reg_r, reg_w; if (INS_OperandCount(ins) != 2) return; reg_r = INS_RegR(ins, 0); // src reg_w = INS_RegW(ins, 0); // dest if (REG_valid(reg_w)){ // reg_w not const(address) if (IsRegTainted(reg_w) && (!REG_valid(reg_r) || !IsRegTainted(reg_r))){ // untainted reg > tainted reg => clear reg *out << "[SPREAD]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; *out << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; removeRegTainted(reg_w); } else if (!IsRegTainted(reg_w) && IsRegTainted(reg_r)){ // tainted reg > untainted reg => tainted *out << "[SPREAD]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; *out << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; taintReg(reg_w); } } } VOID Instruction(INS ins, VOID *v){ if (IMG_IsMainExecutable(IMG_FindByAddress(INS_Address(ins)))){ // callback for read instruction // memory -> reg if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ if (start_taint){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, IARG_PTR, ins, IARG_MEMORYOP_EA, 0, IARG_END); } } // callback for write instruction // reg -> memory else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ if (start_taint){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, IARG_PTR, ins, IARG_MEMORYOP_EA, 0, IARG_END); } } // callback for spread instruction // reg -> reg else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ if (start_taint){ //*out << "[Spread][0x" << std::hex << INS_Address(ins) <<"] : " << INS_Disassemble(ins) << endl; INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)spreadReg, IARG_PTR, ins, IARG_END); } } } } VOID Image(IMG img, VOID *v){ // fgets(&Buf, 2000, File); RTN fgetsRtn = RTN_FindByName(img, "fgets"); if (RTN_Valid(fgetsRtn)) { RTN_Open(fgetsRtn); RTN_InsertCall(fgetsRtn, IPOINT_BEFORE, (AFUNPTR)fgetsBefore, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_END); RTN_Close(fgetsRtn); } // recv(sock, &buf, 2000, 0); RTN recvRtn = RTN_FindByName(img, "recv"); if (RTN_Valid(recvRtn)) { RTN_Open(recvRtn); RTN_InsertCall(recvRtn, IPOINT_BEFORE, (AFUNPTR)recvBefore, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_FUNCARG_CALLSITE_VALUE, 3, IARG_END); RTN_Close(recvRtn); } } VOID Fini(INT32 code, VOID *v){ /* list<ADDRINT>::iterator li; for(li=addressTainted.begin(); li!=addressTainted.end(); li++){ * out << std::hex << *li << endl; } */ *out << "[+] Finish!!" << endl; } ///////////////////////////// ////// call trace ///////// ///////////////////////////// const string *Target2String(ADDRINT target) { string name = RTN_FindNameByAddress(target); if (name == "") { return &invalid; } else if (name == ".text" || name == "unnamedImageEntryPoint") { return new string(StringFromAddrint(target)); } else return new string(name); } string ReadCString(ADDRINT target){ ADDRINT Buffer; PIN_SafeCopy(&Buffer, (ADDRINT *)(target), sizeof(ADDRINT)); string cstring; while (1) { char c = 0; if (PIN_SafeCopy(&c, (ADDRINT *) Buffer, 1) != 1) break; if (c == 0) break; cstring += c; Buffer += 1; } return cstring; } VOID do_call_args(ADDRINT ins,const string *s, ADDRINT arg0, ADDRINT arg1, ADDRINT arg2, ADDRINT esp) { PIN_LockClient(); string img_name = IMG_Name(IMG_FindByAddress(ins)); PIN_UnlockClient(); string base_img_name = img_name.substr(img_name.find_last_of("/\\") + 1); string argstr1 = ReadCString(esp); string argstr2 = ReadCString(esp+4); string argstr3 = ReadCString(esp+8); bool tainted_func = false; if ( IsMemTainted(arg0) ) { tainted_func = true; } if ( IsMemTainted(arg1) ) { tainted_func = true; } if ( IsMemTainted(arg2) ) { tainted_func = true; } if ( tainted_func ) { *out << "[tainted arg]" << StringFromAddrint(ins) << " : " << base_img_name << "!" << *s << "(0x" << std::hex << arg0 << ", 0x" << arg1 << ", 0x" << arg2 << "...)" << endl; if (argstr1.length()>10){ argstr1 = argstr1.substr(0,10); argstr1 += "..."; } if (argstr2.length()>10){ argstr2 = argstr2.substr(0,10); argstr2 += "..."; } if (argstr3.length()>10){ argstr3 = argstr3.substr(0,10); argstr3 += "..."; } *out << " arg1 : " << argstr1 << endl; *out << " arg2 : " << argstr2 << endl; *out << " arg3 : " << argstr3 << endl; } } VOID do_call_args_indirect(ADDRINT ins, ADDRINT target, BOOL taken, ADDRINT arg0, ADDRINT arg1, ADDRINT arg2, ADDRINT esp) { if ( !taken ) return; const string *s = Target2String(target); do_call_args(ins, s, arg0, arg1, arg2, esp); if (s != &invalid) delete s; } /* ===================================================================== */ VOID Trace(TRACE trace, VOID *v) { PIN_LockClient(); IMG img = IMG_FindByAddress(TRACE_Address(trace)); PIN_UnlockClient(); // if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); if ( INS_IsCall(tail) ) { if ( INS_IsDirectBranchOrCall(tail) ) { // direct call const ADDRINT target = INS_DirectBranchOrCallTargetAddress(tail); INS_InsertPredicatedCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args), IARG_INST_PTR, IARG_PTR, Target2String(target), IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_REG_VALUE, REG_ESP, IARG_END); } else { // indirect call INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_REG_VALUE, REG_ESP, IARG_END); } } else { RTN rtn = TRACE_Rtn(trace); if ( RTN_Valid(rtn) && !INS_IsDirectBranchOrCall(tail)) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_FUNCARG_CALLSITE_VALUE, 0, IARG_FUNCARG_CALLSITE_VALUE, 1, IARG_FUNCARG_CALLSITE_VALUE, 2, IARG_REG_VALUE, REG_ESP, IARG_END); } } } } } ///////////////////////////////////////////////// ////////////// call trace end /////////////////// ///////////////////////////////////////////////// int main(int argc, char *argv[]){ PIN_InitSymbols(); if ( PIN_Init(argc,argv) ){ return -1; } string fileName = "taint_analysis_result.txt"; if (!fileName.empty()) { out = new std::ofstream(fileName.c_str());} IMG_AddInstrumentFunction(Image, 0); INS_AddInstrumentFunction(Instruction, 0); TRACE_AddInstrumentFunction(Trace, 0); PIN_AddFiniFunction(Fini, 0); PIN_StartProgram(); return 0; }
실행결과
[Taint] fgets() : buf : 0x12f76c size : 0x7d0 [tainted arg]0x0040113e : reader_taint.exe!myreadfile(0x12f76c, 0x61616161, 0x61616161...) arg1 : aaaaaaaaaa... arg2 : arg3 : [Read][0x401029] : mov dl, byte ptr [ecx+0x5] dl is now tainted 0x12f55f is now tainted [Read][0x401035] : mov cl, byte ptr [eax+0x6] cl is now tainted 0x12f55d is now tainted [Read][0x401041] : mov al, byte ptr [edx+0x8] al is now tainted 0x12f55e is now tainted [Write][0x40104d] : mov byte ptr [ecx+0x2], 0x66 0x12f76e is now freed [Write][0x401054] : mov byte ptr [edx+0x4], 0x67 0x12f770 is now freed [Write][0x40105b] : mov byte ptr [eax+0xb], 0x68 0x12f777 is now freed [Write][0x401062] : mov byte ptr [ecx+0x15], 0x6d 0x12f781 is now freed [tainted arg]0x00401071 : reader_taint.exe!strcpy(0x12f560, 0x12f76c, 0x61616101...) arg1 : arg2 : aafagaaaaa... arg3 : [tainted arg]0x004010a0 : reader_taint.exe!main(0x401143, 0x12f76c, 0x61666161...) arg1 : ƒÄëë3À‹... arg2 : aafagaaaaa... arg3 : [+] Finish!!
'Reversing' 카테고리의 다른 글
암호학 정리(for CTF) (0) | 2018.04.05 |
---|---|
WinDBG 고급 명령어들 (0) | 2017.06.07 |
DBI - Frida 를 이용한 DBI (3) | 2016.09.07 |
Embedded 기기 리버싱 - 펌웨어 리버싱 (1) | 2016.07.14 |
Windbg 기본 - (3) 분석시 유용한 명령어들 (2) | 2016.03.01 |