티스토리 뷰

리버싱

DBI PIN tool 사용하기

삼전동해커 2022. 1. 18. 13:18

PIN tool은 동적으로 바이너리를 분석하기 위해 사용하는 도구이다.

이 도구를 활용해 프로그램 run time시에 코드를 삽입해 Recompile과 Relink가 필요없기 때문에 작업의 효율성이 높고, 실행 중에 발생하는 동작이나 코드를 처리할 수 있다.

 

pin은 JIT 컴파일러로 프로그램을 실제 실행하는 시점에 기계어로 번역하는 방법이다.

이 방법은 컴파일과 인터프리트 방법을 혼합해 사용하는 방법이다.

 

pin 실행

 

pin을 설치하면 다음과 같이 다운로드가 된다.

먼저 보이는 pin.exe는 32비트에서 사용하는 pin 프로그램이고 64비트 환경에서는 intel64\bin 디렉토리 내에 있는 pin.exe를 사용해야 한다.

 

pin 실행 준비

 

source\tools\ManualExamples 디렉토리를 보면 다음과 같은 코드들이 들어있다.

 

이 코드들을 이용해 프로그램을 분석할 수 있다.

예를 들어 inscount1.cpp 코드는 프로그램에서 사용하는 명령어의 갯수를 출력해주는 코드이다.

 

make

makefiles.rules를 이용해 위 코드들 전체를 컴파일해 dll파일을 만들 수 있다.

 

makefiles.rules 파일 실행

 

위 부분에 컴파일할 파일 이름을 넣어 make를 할 수 있다.

윈도우 환경에서는 make 명령어가 없으므로 cgwin과 visual studio를 이용해 make를 실행할 수 있다.

 

make가 실행된다는 가정하에 visual studio command prompt를 실행한 후 ManualExamples 디렉토리에서 다음과 같이 make 명령어를 실행한다.

 

make 명령어를 실행

에러 없이 실행이 완료되면 ManualExamples 디렉토리에 obj-intel64 디렉토리와 -p 디렉토리가 생성된다.

 

make 명령어 결과

이 중 obj-intel64 디렉토리에 pin에서 사용하는 dll 파일들이 들어있다.

pin 사용법

 

먼저 실행에 용이하게 pin 명령어를 환경 변수에 등록한다.

 

환경 변수 등록

다음은 pin을 사용해 분석할 프로그램이다.

 

hyper.cpp

간단하게 input이 0x31337(=201527)이면 cong을 출력하는 프로그램이다.

이 코드를 exe파일로 컴파일한 후 pin으로 dll을 붙여 분석하면 된다.

 

pin -t [dll 경로] -- [실행 파일 경로]

 

위 페이로드를 이용해 pin을 실행해보자.

 

pin 페이로드
pin 실행 결과

위와 같이 cong.dll을 이용해 명령어 주소들을 출력했다.

 

이제 dll을 만드는 코드들을 살펴보자.

아래 코드는 inscount0.cpp를 분석했다.

 

API들의 생성 루틴은 다음과 같다.

구분 내용
PIN_XXXX PIN툴에 대한 전체 영향을 미치는 API
IMG_XXX 하나의 IMG에 영향을 미침
RTN_XXX 함수나 Basic Block에 영향을 미침
INS_XXX 하나의 Instruction에만 영향

 

소스코드는 main문을 먼저보면서 해당 콜백 등록 함수를 본다.

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

// ofstream을 이용해 파일 입력 관리
ofstream OutFile;

// icount에 명령어 개수 관리
// 컴파일러가 docount함수를 활요할 수 있게 icount를 static으로 선어
static UINT64 icount = 0;

// docount함수는 명령이 실행될 때마다 실행됨
VOID docount() { icount++; }
    
// Instruction명령은 새로운 명령어를 만날 때마다 실행됨
VOID Instruction(INS ins, VOID *v)
{
    // 각각의 명령마다 콜백 함수를 지정한다. ins(각 명령) 앞에(BEFORE) 함수(docount)를 call한다.
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
    "o", "inscount.out", "specify output file name");

// 프로그램 종료 시 실행되는 함수
VOID Fini(INT32 code, VOID *v)
{
    // setf(ios::showbase)로 출력에 진법을 표시한다.(0,0x 등)
    OutFile.setf(ios::showbase);
    OutFile << "Count " << icount << endl;
    OutFile.close();
}

/* ===================================================================== */
/* Print Help Message                                                    */
/* ===================================================================== */

INT32 Usage()
{
    cerr << "This tool counts the number of dynamic instructions executed" << endl;
    cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
    return -1;
}

/* ===================================================================== */
/* Main                                                                  */
/* ===================================================================== */
/*   argc, argv are the entire command line: pin -t <toolname> -- ...    */
/* ===================================================================== */

int main(int argc, char * argv[])
{
    // pin을 초기화하는 함수이다. 필수적으로 넣어야함.
    if (PIN_Init(argc, argv)) return Usage();

	//로그를 기록하기 위한 파일 오픈 명령.KNOB에 대한 설명은 아래에서..
    OutFile.open(KnobOutputFile.Value().c_str());

    // 각 명령마다 콜백함수를 지정하기 위해 Instruction()함수를 사용.
    INS_AddInstrumentFunction(Instruction, 0);

    // 함수 종료시에 실행하는 함수 등록.
    PIN_AddFiniFunction(Fini, 0);
    
    // pin 시작 함수
    PIN_StartProgram();
    
    return 0;
}

 

'리버싱' 카테고리의 다른 글

PinTool Opcode binary 출력 구현  (0) 2022.02.14
Opcode에 대해  (0) 2022.02.07
PIN API에 대해  (0) 2022.01.18
abex crackme 4  (0) 2021.02.18
abex crackme 3  (0) 2021.02.18
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함