tcp, zip, tar, png등 다양한 데이터 형식에서는 crc 체크를 통해서 파일의 무결성을 검증한다. 만약 crc 체크가 실패하면 프로그램이 그냥 종료된다. 퍼저에 의해 무작위로 변이된 데이터가 crc를 맞출 수 있을 확률이 지극히 낮다. 이러한 문제를 해결하기 위해서 2가지 방법을 쓸 수 있다.
- Post mutator에 crc 체크를 맞춰주는 코드를 넣어준다.
- 장점1 : Crash reproduce가 쉽다.
- 장점2 : crc뿐만 아니라, 다른 형식에 대해서도 적용할 수 있기 때문에 더 범용적이다.
- 단점1 : 하나의 포맷이 아니라, 다수의 포맷을 처리하는 프로그램의 경우, 프로그램에서 어떠한 방식으로 파일의 포맷을 결정하는지 리버싱해야 한다.
- switch(format(data)){//have to reversing format function case ZIP: unzip(data) case TAR: untar(data) case TCP: handle_tcp(data) }
- 단점2: 데이터 포맷에 대한 이해가 필요하다.
2. Fuzzing할 바이너리에서 crc 체크 코드를 삭제해준다.
- 장점1 : 쉽다.
- 장점2 : 자동화를 할 여지가 많다.
- 단점1 : 바이너리를 임의로 패치했기 때문에, 실제로는 reproduce되지 않는 크래시일 수 있다.
- 단점2 : 다수의 데이터 포맷을 처리하는 경우, 가장 처음 체크하는 포맷 외에는 제대로 검증되지 않을 수 있다.
- if is_zip(data): #==> No format error, so always True. unzip(data) elif is_tar(data):#==> unfuzzable untar(data)
소스코드가 있다면, crc코드를 간단하게 삭제할 수 있지만, strip된 바이너리에서는 crc 체크 구문을 찾기 힘들 수 있다. Fuzzing할 바이너리에서 crc 체크 코드를 삭제하기 위해서는 바이너리를 리버싱한 후, 어디에서 crc 체크가 이루어지는지 찾아야 한다. 하지만, 데이터의 crc값이 무엇인지 알고 있다면, pintools를 이용해서 crc 체크가 이루어지는 위치를 자동으로 찾을 수 있다.
아래는 cmptrace.cpp를 약간 수정한 코드이다. 프로그램이 돌아가면서 실행되는 모든 cmp 명령어를 로깅한다.
// cmptrace.cpp
//https://github.com/inaz2/pintools/blob/master/cmptrace.cpp
#include <cstdio>
#include "pin.H"
#include <iostream>
#include<fstream>
using namespace std;
std::ostream* out = &std::cerr;
VOID log_f(){
string fileName = "trace";
out = new std::ofstream(fileName.c_str());
}
VOID print_cmp_mem(VOID *ip, UINT64 * addr, ADDRINT value) {
PIN_LockClient();
IMG img = IMG_FindByAddress((unsigned long )ip);
unsigned long base = IMG_LowAddress(img);
string name = IMG_Name(img);
*out <<name << " + 0x"<<hex<< (unsigned long )ip -base << " : cmp 0x" <<*addr<<" , 0x"<<value<< endl ;
PIN_UnlockClient();
}
VOID print_cmp_reg(VOID *ip, ADDRINT lvalue, ADDRINT rvalue) {
PIN_LockClient();
IMG img = IMG_FindByAddress((unsigned long )ip);
if(!IMG_Valid(img)){
return;
}
unsigned long base = IMG_LowAddress(img);
string name = IMG_Name(img);
*out <<name << " + 0x"<<hex<< (unsigned long )ip -base << " : cmp 0x" <<lvalue<<" , 0x"<<rvalue<< endl ;
PIN_UnlockClient();
}
VOID Instruction(INS ins, VOID *v)
{
if (INS_Opcode(ins) == XED_ICLASS_CMP) {
if (INS_MemoryOperandCount(ins) == 1) {
if (INS_OperandIsImmediate(ins, 1)) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)print_cmp_mem, IARG_INST_PTR, IARG_MEMORYOP_EA, 0, IARG_ADDRINT, INS_OperandImmediate(ins, 1), IARG_END);
} else if (INS_OperandIsReg(ins, 0)) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)print_cmp_mem, IARG_INST_PTR, IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_END);
} else {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)print_cmp_mem, IARG_INST_PTR, IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_END);
}
} else {
if (INS_OperandIsImmediate(ins, 1)) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)print_cmp_reg, IARG_INST_PTR, IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_ADDRINT, INS_OperandImmediate(ins, 1), IARG_END);
} else {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)print_cmp_reg, IARG_INST_PTR, IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_END);
}
}
}
}
int main(int argc, char *argv[])
{
log_f();
PIN_Init(argc, argv);
INS_AddInstrumentFunction(Instruction, 0);
PIN_StartProgram();
return 0;
}
pintools로 모든 cmp 명령어를 덤프하고, 그중에서 crc 값이 사용되는 주소를 찾은 후 패치하면 된다.
➜ cmp git:(main) ✗ ../../../pin -t ./obj-intel64/cmp.so -- ./target지워짐 passwd.gz
➜ cmp git:(main) ✗ gzip -lv passwd.gz
method crc date time compressed uncompressed ratio uncompressed_name
defla 29a74433 Nov 19 15:52 1035 2801 63.9% passwd
➜ cmp git:(main) ✗ cat ./trace|grep 29a74433
/home/jjy/inturn/pin/source/tools/cmp/target__지워짐.so : cmp 0x29a74433 , 0x29a74433
/home/jjy/inturn/pin/source/tools/cmp/target__지워짐.so : cmp 0x29a74433 , 0x29a74433
참조
https://github.com/inaz2/pintools/blob/master/cmptrace.cpp
'PWN' 카테고리의 다른 글
AFLPlusplus qemu, Persistence mode 속도 느려질 때 (0) | 2022.01.04 |
---|---|
AFLPlusplus - qemu mode - High map density (0) | 2021.10.22 |
Linux 버그 보는 곳 (1) | 2021.06.06 |
Ida python for bug hunting (0) | 2021.03.11 |
Assaultcube Fuzzing (0) | 2021.02.04 |