취약점분석/Fuzzing

Hybrid Fuzzing - 2 ( SymCC + AFL )

poiri3r 2026. 1. 15. 19:41

https://github.com/eurecom-s3/symcc/blob/master/docs/Fuzzing.txt

 

symcc/docs/Fuzzing.txt at master · eurecom-s3/symcc

SymCC: efficient compiler-based symbolic execution - eurecom-s3/symcc

github.com

 

해당 링크의 설치 안내를 보고 한번 환경 구성을 해보겠습니다. 

 

공식 SymCC 저장소 다운로드

git clone https://github.com/eurecom-s3/symcc.git

 

 
FROM ubuntu:22.04 AS builder
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y cargo cmake g++ git libz3-dev ninja-build python3-pip zlib1g-dev wget build-essential python3-dev automake flex bison libglib2.0-dev libpixman-1-dev libpython3.10 clang llvm && pip3 install lit
WORKDIR /
RUN git clone https://github.com/AFLplusplus/AFLplusplus.git afl && cd afl && make
COPY . /symcc_source
FROM builder AS builder_qsym
WORKDIR /symcc_build
RUN cmake -G Ninja -DSYMCC_RT_BACKEND=qsym -DCMAKE_BUILD_TYPE=RelWithDebInfo -DZ3_TRUST_SYSTEM_VERSION=on /symcc_source && ninja && cargo install --path /symcc_source/util/symcc_fuzzing_helper
FROM ubuntu:22.04 as symcc
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential g++ zlib1g sudo libglib2.0-0 libpixman-1-0 vim git cmake python3 clang llvm libz3-dev && useradd -m -s /bin/bash ubuntu && echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/ubuntu
COPY --from=builder_qsym /symcc_build /symcc_build
COPY --from=builder_qsym /root/.cargo/bin/symcc_fuzzing_helper /usr/bin/
COPY --from=builder /afl /afl
ENV PATH="/symcc_build:/afl:$PATH"
ENV AFL_PATH="/afl"
WORKDIR /work
CMD ["/bin/bash"]

도커파일에서 맨 마지막에 COPY로 빌드된 AFL을 가져와서 dockerfile을 변경해뒀습니다.

git submodule update --init --recursive
docker build -t hybrid_fuzz .

 

이렇게 빌드해줍니다.

빌드까진 문제 없이 성공한 것 같습니다.

symcc와 afl-fuzz, helper도 다 인식이 잘 됩니다.

 

테스트용 코드를 가져와보겠습니다. 하다가 넘 안되서 중간중간 디버깅용 printf를 넣었습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv) {
  FILE *f;
  char buf[10];

  // 인자 확인
  if (argc < 2) {
    printf("Usage: %s <input_file>\n", argv[0]);
    return 1;
  }

  // 파일 열기
  f = fopen(argv[1], "rb");
  if (!f) {
    printf("DEBUG: Failed to open file! Check path: %s\n", argv[1]);
    return 1;
  }

  // 파일 읽기
  if (fread(buf, 1, 4, f) < 4) {
    printf("DEBUG: Read failed or file too short\n");
    fclose(f);
    return 0;
  }
  buf[4] = '\0';
  fclose(f);

  // 경로로 확인용 로그
  if (buf[0] == 'S') {
    printf("DEBUG: [Branch 1] Found 'S'! Going deeper...\n");
    if (buf[1] == 'y') {
      if (buf[2] == 'm') {
        if (buf[3] == '!') {
          abort();
        }
      }
    }
  } else {
    printf("DEBUG: [Branch 2] First char is '%c', not 'S'. Exiting.\n", buf[0]);
  }

  return 0;
}

 

그리고 symcc버전 afl버전 각각 컴파일 해줍니다.

symcc -o target_sym target.c
afl-cc -o target_afl target.c

 

그리고 이전에 했을 때 afl에서 symcc가 발견하고 queue파일에 넣은 값들을 못읽어오는게 문제였던것같은데,  afl에서 queue에 있는 파일을 읽으면서 가져올 때 해시값을 비교하면서 가져오는데, 이유모르게 다른 글자여도 같은 해쉬값으로 취급을 했던 문제가 있었습니다.

그래서 디버깅용 코드를 넣고 다시 컴파일해서 확인해보니 되더라고요

 

symcc가 만든 queue파일을 보면 id가 0부터 4까지 Sym!을 찾기위한 중간 과정들이 queue에 저장됩니다.

 

fuzzer_out폴더에 afl_master라는 폴더도 생성되는데 afl이 관리하는 queue폴더에는 다음과 같이 들어있습니다.

여기서 sync:symcc_node는 SymCC가 분석한 파일을 토대로 문제를 찾았다는걸 의미합니다.

 

afl-fuzz 화면은 다음과 같습니다.

 

여기서 imported값이 2가 되었는데 symcc로부터 받은 값이 2개라는것을 의미합니다.

예제 코드 자체가 if문에 한글자씩밖에 안들어있어서 두글자는 afl에서 랜덤대입으로 때려맞췄네요.,

 

여태까지 실패했던 원인을 정확하게 분석을 못하겠는데 .. 지금 천천히 생각해보면 터미널을 두개 띄워두고 하니까 그 두 터미널사이의 파일간의 괴리가 조금 있었던 것 아닌가 싶네요

 

일단 이것으로 하이브리드 퍼징에 대한 포스팅을 마치겠습니다.

글은 굉장히 짧아 보이지만 포스팅이 없었던 기간만큼의 고뇌를 거친 포스팅입니다..

읽어주셔서 감사하고, 한국어로 된 symcc fuzzing 포스팅을 못찾았어서, 만약에 해보고자 하시는 분이 계신데 잘 안되는 부분이 있다면 댓글로 남겨주시면 아는만큼 답변 드리겠습니다.

감사합니다

'취약점분석 > Fuzzing' 카테고리의 다른 글

Hybrid Fuzzing - 1 ( 실패일지 )  (0) 2026.01.15
SymCC Fuzzing - 1 ( Symbolic executor )  (0) 2026.01.11
[Fuzzing] Boofuzz Fuzzing  (0) 2026.01.09
[Fuzzing] AFL++ Fuzzing  (0) 2026.01.08