2017-10-09 1 views
2

인텔 PIN을 사용하여 응용 프로그램의 지침을 수정하고 있습니다. 나는 참고로이 링크에서 Safecopy() 예를 사용하고 -PIN의 응용 프로그램 수정 수정

https://software.intel.com/sites/landingpage/pintool/docs/81205/Pin/html/index.html#SafeCopy

I 다음 샘플 C의 프로그램 -

int main() 
{ 
    asm(".byte 0x16"); 
    return 0; 
} 

0 * 16는 x86_64의에서 불법하고 난 실행 파일을 실행할 때 그것은 예상대로 다음과 같은 오류 표시 -

Illegal instruction (core dumped) 

을 내가 입력으로 위의 실행 파일을 받아 불법 난을 수정하는 pintool이 nstruction 0x16 다른 것을하기 위해.

#include "pin.H" 
#include <iostream> 
#include <fstream> 

using namespace std; 

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","This pin tool simulates ULI"); 

FILE * op; 

//==================================================================== 
// Analysis Routines 
//==================================================================== 

VOID analysis_routine(VOID *ip, UINT32 size) 
{ 

    fprintf(op,"16 came to analysis routine\n\n"); 
} 


//==================================================================== 
// Instrumentation Routines 
//==================================================================== 

VOID Instruction(INS ins, void *v) 
{ 

    UINT8 opcodeBytes[15]; 

    UINT64 fetched = PIN_SafeCopy(&opcodeBytes[0],(void *)INS_Address(ins),INS_Size(ins)); 

    if (fetched != INS_Size(ins)) 
     fprintf(op,"\nBad\n"); 

    else 
    { 
     if(opcodeBytes[0]==0x16) 
     { 

      fprintf(op,"\n16 came to instrumentation routine\n"); 

      INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, IARG_INST_PTR, IARG_UINT64, INS_Size(ins) , IARG_END); 
      INS_Delete(ins); 
     } 
    } 
} 

VOID Fini(INT32 code, VOID *v) 
{ 
} 

INT32 Usage() { 
    PIN_ERROR("This Pintool failed\n" + KNOB_BASE::StringKnobSummary() + "\n"); 
    return -1; 
} 

int main(int argc, char *argv[]) 
{ 

    op = fopen("test.out", "w"); 

    if (PIN_Init(argc, argv)) 
     return Usage(); 

    PIN_InitSymbols(); 
    INS_AddInstrumentFunction(Instruction, 0); 
    PIN_AddFiniFunction(Fini, 0); 
    PIN_StartProgram(); 
    return 0; 
} 

을 계측 루틴 명령은 매번 실행되는 새로운 지시가 발생하고 명령은 다음과 같이 실행되기 전에 내 코드에 따라, 분석 루틴이 호출 내 이해에 따르면 - 다음과 같이

내 Pintool입니다 내 계측 함수에서 IPOINT_BEFORE 인수를 사용하여 분석 루틴을 호출합니다. 따라서 내 opcode를 확인하고 0x16이면 분석 루틴을 호출하고 원래 명령을 삭제합니다. 설치가 불법이고 삭제 되었기 때문에 아무런 문제없이 내 추적이 더 진행되어야합니다.

그러나이 논리를 사용하더라도 내 불법적 인 명령이 실행되고 내 프로그램이 충돌하고 잘못된 명령 오류가 발생하는 것으로 보입니다. 실행하기 전에 명령을 삭제하는 것처럼 보이고 Pin 자습서에서 같은 예제를 사용하고 있으므로이 문제를 이해할 수 없습니다.

내가 잘못 생각하면 어떤 아이디어가 있습니까? 또한 내가 위의 어느 곳에서든지 틀린 경우에 또한 나를 정정하십시오. 내 이해에 따라 계측 루틴은 명령이 실행되기 전에 호출되므로 해당 시간에도 명령을 수정할 수 있습니다. 내가 틀렸다면 나를 바로 잡아주세요.

+0

올바른 주소로 올바른 바이트를 바꾸시겠습니까? 문제의 원인이되는 1 바이트 만 바꾸는 것이 확실합니까? 해당 단일 바이트를 다른 바이트 패턴으로 만 바꾸고 있습니까? 0x16은 자체적으로 법적 명령이 아닐 수도 있지만 더 큰 명령의 일부로 해석되지 않는 것을 어떻게 확인합니까? – nitzanms

답변

0

INS_Delete()는 인스트루멘테이션시, 즉 명령어가 실제로 실행되기 전에 인스트루먼트 루틴이 호출되기 전에 호출된다는 사실을 알아야합니다. 이벤트가 발생하는 순서는 다음과 같다 : INS_Delete (인)가 호출되면

INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, ...); 
INS_Delete(ins); 
analysis_routine(); /* <= BOOM ! ins had been deleted just before... */ 

, 당신은 당신의 도구가 일관성없는 그렇지 않으면 그것으로가는 모든 장비를 제거해야합니다. 계기가 남아 있다고 가정하면 계측 루틴과 관련된 명령은 예상 한 것이 아니므로 충돌이 발생합니다.

이 점을 더 잘 이해하려면 (처음에는 올바르게하기가 쉽지 않음) pin works을 다시 읽는 것이 좋습니다.

편집 :는 도구 (아래 설명 참조) 패키지 몇 가지 공식 pintools에 따르면, 악기는 패턴이 PIN의 규칙적인 패턴입니다 삭제합니다.

+2

PIN을 전혀 사용하지 않았지만 궁금합니다. 왜'INS_Delete()'를 사용하고 나서'analysis_routine()'을 호출하는 것이 문제일까요? INS_Delete()는 정확히 무엇을합니까? 대답을 읽는 사람들이 PIN을 올바르게 사용하는 방법을 이해하지 못한다고 가정합니다. 그렇지 않으면이 문제가 발생하지 않습니다. 적어도 그것이 잘못되었다는 것을 지적 할뿐만 아니라 그것을 설명하는 문서의 부분에 링크하십시오. –

+0

피터 감사합니다. 그에 따라 대답이 업데이트되었으므로 도움이되기를 바랍니다. – Heyji

+0

아, 그래서'INS_Delete (ins)'는 실제로 실행될 명령에서 명령을 제거하는 것이 아니라 계측을 삭제합니다. 네, 이름을 기반으로 원하는 기능을 수행하기를 바라는 대신 문서를 읽는 것이 좋습니다. : P 이것은 @ Rohit의 일련의 모든 질문에 대한 답변입니다. –

1

여기에 무슨 일이 생길지 모르겠지만, 여기에 내가 할 일이 있습니다. 나는 계측 루틴에서 명령에 대한 훨씬 더 많은 정보를 인쇄하는 것으로 시작할 것입니다.

  • 얼마나 걸리나요?
  • 이 지침에는 어떤 주소가 있습니까? 테스트 프로그램에서 main()의 주소를 출력하여 둘이 서로 가깝게 있는지 확인하십시오.
  • 다른 명령어 바이트는 무엇입니까? 불법 바이트를 따르는 명령어와 일치하는 바이트가 발생합니까?

Aditionally :

  • 출력 파일이 잘못된 명령 오류가 나는 SIGILL 신호를 잡는 것이 좋습니다 디버그 인쇄
  • 을 마스크 발생하지 않도록하기 위해, 모든 인쇄 후 플러시되어 있는지 확인합니다 귀하의 프로그램이 아마도 핀을 사용하거나 사용하지 않고 같은 장소에서 일어나고 있는지 확인해야합니다.
+0

INS_Size (ins)를 사용하여 명령어 크기를 얻습니다. . 내가 INS_Address (ins)을 사용하여 주소를 얻습니다. INS_Size (ins) 바이트를 명령 주소의 포인터에서 복사 할 때 명령 바이트를 모두 가져옵니다.이 명령은 내 명령 추적의 디스 어셈블리로 확인한 것과 일치합니다. –

+0

거기에 내가하는 것이 좋습니다 다른 수표가 있습니다. – nitzanms