• [S&P][AI][SECURITY] Asm2Vec: Boosting Static Representation Robustness for Binary Clone Searchagainst Code Obfuscation and Compiler Optimization 논문 리뷰

    2021. 2. 12.

    by. ugonfor

     

     

    논문 전부를 읽을 시간이 없는 바쁜 사람들을 위해...

    위 논문은 결국 어셈블리 instruction을 Word2Vec처럼 어셈블리를 벡터로 표현하여 모델을 구현하고 학습시킬 수 있다는 것을 설명하며, 이를 이용하게 되면 난독화되어 있거나 컴파일러 최적화 옵션이 달라도 우수한 성능으로 code clone을 정적분석으로 검색해낼 수 있다는 내용을 다루고 있다.

     

    이 내용을 ASM을 Vector로 표현하는 법, Training Model, Experiment(난독화 / 컴파일러 최적화 옵션 변화) 에 대해서 구체적으로 다룬 논문이다.


    목차

    논문 목차는 다음과 같습니다.

    1. Introduction

    2. Problem Definition

    3. Overall Workflow

    4. Assembly Code Representation Learning

    4.1. Preliminaries

    4.2. The Asm2Vec Model

    4.3. Modeling Assembly Functions

    4.3.1. Selective Callee expansion.

    4.3.2. Edge Coverage

    4.3.3. Random Walk.

    4.4. Training, Estimating and Searching

    5. Experiments

    5.1. Searching with Different Compiler Optimization Levels

    5.2. Searching with Code Obfuscation

    5.3. Searching against All Binaries

    5.4. Searching Vulnerability Functions

    6. Related Work

    7. Limitations and Conclusion

     

    목차 5이후에 대한 이야기는 대부분 기술적인 이야기보다는 실험을 어떻게 진행했고 어떻게 성능이 나타났는 지 알려주는 내용인 데, 대부분 Asm2Vec이 아주 짱짱하다는 이야기이고, 어려운 내용도 기술적인 부분도 별로 없어서 간단히 표, 그림 위주로 설명하고 넘어가겠습니다.

     


    논문을 드디어 다 읽고왔습니다.

    함께 논문 리뷰 시작하겠습니다.

    Introduction

    Introduction에서는 Asm2Vec이 왜 필요한지?에 대한 서술이 대부분을 이루고 있습니다.

     

    최근 개발자들의 코드를 보게 되면 처음부터 설계를 다 하고, 빈페이지에서 코드를 짜는 거의 없습니다.

    대부분 코드를 ctrl+c, ctrl+v 를 하는 경우가 많습니다. 여기서는 이런 이런 복붙을 보고 "clone" 이라고 하였습니다.

    근데 이런 Clone들이 많아지게 되면 보안적으로 문제가 생깁니다. 취약점이 있는 코드가 그대로 clone되어 다른 바이너리에 사용되는 경우가 많아지기 때문이죠. 그래서 Clone Search는 보안적으로 중요한 문제입니다!

    밈 재밌네요 ㅋㅋ

    근데, Clone Search Engine을 개발하는 것은 쉬운것이 아닙니다. 

    같은 소스코드를 가지고 컴파일을 해도 컴파일하는 컴파일러에 따라서 CFG(control flow graph)가 바뀌게 되고, 같은 컴파일러를 사용해도 컴파일 최적화 옵션에 따라서 코드가 전혀바뀌게 됩니다. 또한, 만약에 난독화라도 적용한 경우에는 소스코드를 보지 않고서는 Reverse Engineer가 보더라도 꽤 시간이 걸려야 Clone인지 구별할 수 있습니다.

     

    아래 사진을 보면 이를 실감할 수 있습니다. 

    아래 사진은 같은 소스코드를 가지고 컴파일, 난독화를 한 바이너리의 같은 function의 CFG입니다. 결국 4가지 CFG모두 같은 역할을 하는 것이지요. (참고로, 놀랍게도 Asm2Vec 모델로 학습시키게 되면, 아래 CFG로 나타난 어셈블리 코드 모두를 Clone임을 구별해낼 수 있다고 한다.)

    Figure 1: Different assembly functions compiled from the same source code of gmpz tdiv r 2exp in libgmp. From left to right, the assembly functions are compiled with gcc O0 option, gcc O3 option, LLVM obfuscator Control Flow Graph Flattening option, and LLVM obfuscator Bogus Control Flow Graph option. Asm2Vec can statically identify them as clones.

    이처럼, Clone Search를 하는 건, 어려운 문제이고 연구할 만한 가치가 있다. (그래서 Asm2Vec을 만들었다!)

     

    이제, Clone Search Solution을 만드려고 하는 데, 이를 위해서는 assembly code를 vector로 표현을 해야할 필요가 있다. (물론, 각각의 feature를 잘 표현하게! (Robust하게!))

    보통 어셈블리를 벡터로 표현을 하고자할 때는 Dynamic하게 접근하는 경우와 Static으로 접근하는 경우 두가지가 있는 데, 정적으로 접근하게 되면 더 많은 부분을 처리할 수 있고 (coverage가 좋고), 동적으로 처리하게 되면, syntax가 변하는 것에 있어서 더욱 정확하게 처리를 할 수 있다. 

     

    이 논문에서는 정적으로 feature를 뽑아내는 과정에서두 개의 문제점을 제시하며 이를 해결하여 static approach를 더욱 semantic richness/ robustness 하게 만들고자 한다.

     

    P1: 기존의 정적분석 방법들은 feature를 뽑아내는 과정에서 feature간의 relationship을 고려하지 못하였다.

    binary를 딥러닝을 통해 분석하려는 시도들은 전에도 꽤나 있었으나, 이들은 모두 각각의 feature를 independent하게 다른 dimension에 표현하였다. 근데 사실은 각각의 feature들이 독립적인 것이 아니라, 서로 연결되어 있기에 이를 고려해야 성능을 더욱 높일 수 있다. (ex, 함수의 calling convention이라든지, 레지스터를 비우는 과정 등은 이후 동작과 연관되어 있다.)

     

    그래서 이 문제를 해결하기위해서 저자는 lexical semantic relationship을 고려한 feature를 생성하는 방법을 만들고자 하였다. 그런데, feature 생성할 때, assembly 간의 관계를 다 고려하려면 굉장히 오랜 시간이 걸리게 될 것이다. 모든 어셈블리에 대해서 다 따로 값들이나, 중요도 등을 설정해줘야 하기 때문이다. 그래서 Asm2Vec이라는 이런 prior knowledge가 필요없는 training process를 개발하였다.

     

    그리고 실제로 아래 사진을 보면 Asm2Vec을 통해서 token들을 고차원에 나타내고 이를 2차원에 투영하여 시각화한 것인데 token 사이의 관계를 잘 나타내고 있는 것을 보여준다. 비슷한 역할을 하는 것들끼리 가까이에 있는 것을 확인할 수 있다. 

     

    Figure 2: T-SNE clustering visualization of tokens appearing in assembly code. There are three categories of tokens: operation, operand, and libc function call. Each token is represented as a 200-dimensional numeric vector. They are learned by Asm2Vec on plain assembly code without any prior knowledge of the assembly language. The training assembly code does not contain the libc callee functions’ content. For visualization, T-SNE reduces the vectors to two dimensions by nearest neighbor approximation. A smaller geometric distance indicates a higher lexical semantic similarity.

     

    P2: 기존 정적분석의 두번째 문제점은 Feature를 모두 동등하게 본다는 것이다. 즉, weight에 정보가 feature에 전혀 반영되어있지 않다. 또는, 만약에 feature에 weight를 적용시키고자 하면, assembly의 중요도를 직접 mapping해주어야 한다.

    리버서가 분석을 할 때를 생각해보게 되면, 모든 로직에 대해서 자세히 분석을 하지는 않는다. 리버서는 보통 경험을 바탕으로 중요한 패턴을 집어내게 되고, 그 부분만을 집중적으로 분석합니다. 나머지 부분들에 대해서는 분석을 별로 하지 않습니다. 그렇기에, 모든 feature에 대해서 동등하게 다루는 것은 clone search에 있어서 좋지 않습니다.

     

    이 문제를 해결하기 위해 저자는 DNN을 설계하여 수많은 어셈블리 코드를 학습시키고, model로 하여금 function에 대한 best representation vector를 생성하게 하고자 하였다.


    그래서 이 논문에서는 다음과 같은 일을 하였고 시사점은 다음과 같다.

    • representation learning을 assembly code에 한 것은 이번이 처음이다.

    • representation learning model for assembly code syntax and control flow graph, Asm2Vec을 만들었다.

    • Asm2Vec을 이용하면, 난독화/코드 최적화에 상관없이 clone search를 아주잘 해낸다. 이는 현재 SOTA 정적, 동적 분석보다 더 좋은 성능을 보인다. (Asm2Vec은 아주 좋다!)

     

    Problem Definition

    이제, Asm2Vec으로 풀려고 하는 문제를 정확히 정의를 하고자 한다.

     

    먼저 용어 정의부터 하자면, 

     

    어셈블리 Clone은 보통 다음 4가지로 분류할 수 있다.

    Type I: literally identical; (동일)
    Type II: syntactically equivalent; (source가 동일)

    Type III: slightly modified (살짝 변화)
    Type IV: semantically similar. (난독화 / 컴파일 옵션 차이으로 코드는 많이 변화, 의미상 동일)

     

    그리고,

     

    \(function\)은 assembly function

    \(source function\)은 source code 단에서 나타나는 함수

    \(repository function\)은 repository에 정의된 어셈블리 함수

    \(target function\)은 assembly 함수 query의 input

     

    을 나타낸다.

     

    이 논문의 목표는 주어진 assembly function에 대해서 semantic clones를 repository RP에서 찾는 것이다. 즉, target function의 Type IV Clone을 repository에서 찾는 것이다. (Assembly function clone search)

     

    영어 원문으로 문제 정의는 다음과 같다.

    문제 정의하는 부분으로 아주 중요하기에 영어 원문을 가져왔다.

    Overall Workflow

    Overall workflow : 이 사진 하나로 끝남

    위 사진이 workflow를 모두 표현한다.

    구체적으로 설명하자면, 4개의 step이 존재한다.

    step 1: 주어진 repository functions에 대해서 DNN model을 생성한다.

    step 2: 각각의 repository function에 대해서 vector representation을 생성한다.

    step 3: target function \(f_t\)가 주어졌을 때, 이에 대해서 vector representation을 계산한다.

    step 4: vector를 비교해서 repository functions와 유사도를 확인하고 top-k ranked candidates를 결과로 뱉는다.

     

    Assembly Code Representation Learning

    이 장에서는 어셈블리 코드의 representation learning에 대해서 다룬다.

    참고로, Asm2Vec의 경우, PV-DM 모델을 기반으로 생성되었다. (PV-DM이란, Doc2Vec의 모델로 문서를 벡터화해주는 모델이다.)

    저자는 Asm2Vec 모델을 수식화하고, Training 하는 방법을 설계해서 PV-DM 모델에 적용하였다. 그리고 Text와는 다르게, assembly code는 linear한 sequenc가 아니기에 multiple sequence를 modeling하는 방법도 설계하였다.

     

    4.1. Preliminaries

    Asm2Vec 모델을 알기 전에 PV-DM 모델에 대해 알아보자

    PV-DM 모델은 word2vec 모델을 확장한 것으로 Paragraph를 vector로 표현하는 방법을 학습한 모델이다. 

    PV-DM model

    PV-DM 모델은 Multi-class prediction인데(vocabrary가 아주 많으니..), pragraph ID Vector, Word ID Vector들의 average를 내고 이에 대해서 softmax classification을 통해서 target word를 확인하게 된다.

     

    PV-DM은 식으로 나타내면 다음과 같다.

    PV-DM은 다음 log prabability를 maximizes한다.

    $$\sum^T_p\sum^p_s\sum^{|s|-k}_{t=k}logP(w_t|p,w_{t-k}, ..., w_{t+k})$$

    $$T : \text{text corpus(본문)}$$

    $$p : \text{paragraph}$$

    $$s : \text{sentences}$$

    $$w_i : \text{word}$$

    $$k : \text{sliding window size}$$

    이다.

     

    위와 같이 PV-DM model을 사용하고 있고, training을 한 word들에 대해서 vector representation을 잘 나타내고 있었다.

     

    하지만, 어셈블리 코드의 경우 syntax가 훨씬 다양하고, 구조적(linearly하지 않고, CFG가 괴상하게 생김.)으로도 다르고, operation, operands 등이 존재하기에 PV-DM모델을 그대로 사용할 수는 없고, 어셈블리 코드에 맞게 변형 시켜야 한다.

     

    그래서 이 논문에서는 assembly code의 syntax를 고려한 representation learning model을 소개한다.

     

     

    4.2. The Asm2Vec Model

    어셈블리 function의 경우 CFG로 표현할 수 있다. (실제로도, 리버서는 어셈블리를 보통 graph로 보며 분석한다.)

    그래서 저자는 CFG를 multiple sequences로 modeling하고자 한다. 

    각각의 sequence들은 CFG를 연결한 것이다 보니, potential execution trace라 할 수 있다. 그리고 나중에 execution을 하게 되면, assembly는 linear하게 실행되기에 linear하게 처리할 수 있다.

     

    논문에서는 IDA Pro disassembler(역시 갓툴)를 CFG를 그리기 위해 사용하였다. 

    4.2 에서는 Figure 3인 overall workflow 사진에서 Step 1, Step 2에 해당하는 부분을 설명한다.

    즉, representation model을 train하고 벡터를 생성하는 부분이다.

     

    representation model training.

    PV-DM 모델처럼 function을 vector representation을 하려면, 각각의 어셈블리 instruction에 대해서, function vector를 참여하여 prediction을 하고, 이에 대해서 feedback을 주어 representation vector를 구해야 한다.

     

    먼저, 각각의 repository function \(f_s\)를 vector \(\vec{\theta_{f_s}} \in \mathbb R^{2\times d }\)로 표현하였다. 

    이때,  \(\vec{\theta_{f_s}}\)는 함수 \(f_s\)의 vector representation이다. d의 경우 사용자가 임의로 결정한 것으로 parameter의 수를 결정한다.

    이를 반복하여 모든 repository functions에 대해서 vector representation을 초기화 한다.

     

    그리고, assmelby code에 대한 token을 구하고, 각각의 vector representation을 구한다. 이 token은 assembly의 operation, operand 등이 이에 해당한다. 

    그래서 each token t에 대해 numeric vector \(\vec v_t \in \mathbb R^d \)와 another numeric vector \(\vec v'_t \in \mathbb R^d \)를 구한다.

    \(\vec v_t\)는 token t에 대한 vector representation으로, figure 2. 에서 각각의 token들을 매핑한 것도 이 vector를 기반으로 표시한 것이다.

     

    \(\vec v_t\)는 token의 vector representation을 위한 것이고, 

    \(\vec v'_t\)는 token prediction을 위한 것이다.

     

    \(\vec v_t\)는 초기화를 0에 가까운 랜덤값으로 하고,

    \(\vec v'_t\)는 0으로 시작한다.

     

    \(f_s\)의 dimension의 경우 \(2 \times d\)로 하는 데, 이는 instruction을 represent하기 위해, operation과 operands의 vector를 concatenate해서 표현하기 때문이다. (이 부분 원래 이해가 어려운 데, 아래 사진을 보게 되면 이해 하기 쉽다.)

     

    Asm2Vec의 전체적인 과정

     

     

    종합하여 논문에서 Asm2Vec을 수식으로 표현을 다음과 같이 하였다.

    Asm2Vec 모델의 목적은 다음식의 값이 최대가 되도록 하는 것이다.

    $$\sum ^{RP}_{f_s} \sum ^{S(f_s)}_{seq_i} \sum ^{I(seq_i)}_{in_j} \sum ^{T(in_j)}_{t_c} log P(t_c| f_s, in_{j-1}, in_{j+1})$$

    $$ \text{treat } f_s \in RP \text{ as multiple sequences } S(f_s) = seq[1:i], where \ seq_i \text{ is one of them.}$$

    $$\text{A sequence is representated as a list of instructions } I(seq_i) = in[1:j], where \ in_j \text{ if one of them.}$$

    $$\text{An instruction } in_j \text{ contains a list of operands } A(in_j) \text{ and one operation } P(in_j). $$

    $$\text{So, their concatenation is denoted as its list of tokens } T(in_j) = P(in_j) || A(in_j), \ where || \text{ denotes concatenation.}$$

     

    즉, 가장 가능성 높은 token을 구하고, instruction을 구하고, seq, f_s를 구해서 결국에는 f_s를 representation하고자 한다.

     

    Figure 5에서 보면, target instruction(빨간색) 되는 instruction의 주위 instruction에 대해서 vectorize를 하고, 이에 function vector까지 참여하여, prediction vector를 생성하고 이에 대해서 실제 vector와 비교하여 feedback을 주어야 한다.

     

    여기서 각각의 instruction의 경우 operation의 token과 operand의 token의 평균을 concat해서 vector로 나타낸다.(이를 \(CT(in)\) 이라 하였다.) 이를 수식으로 나타내면 다음과 같다. 

    $$ CT(in) = \vec v_{p(in)}||\frac{1}{|A(in)|}\sum^{A(in)}_t \vec{v_{t_b}} $$

    $$p(in) \text{denotes an operation and it is a single token}$$ 

     

    그리고, \(f_s\)와 \(CT(in_j-1)\), \(CT(in_j+1\)을 구해서 average를 하여 각각의 데이터를 다 포함하고 있는 vector \(\delta(in,f_s)\) 를 구한다.

     

    이를 이용하면, 식을 다음과 같이 변화시킬 수 있다.

    $$P(t_c| f_s, in_{j-1}, in_{j+1}) = P(t_c|\delta(in_j,f_s))$$

     

    이에 우리가 필요로 하는 vector \(\vec v\)와 \(\vec v'\)이기에 이를 위 식에 넣어주어야 한다.

    위 식에서 \(t_c\)의 경우 \(\vec v'_{t_c}\)로 표현가능하다. (실제로, \(\delta(in_j,f_s)\)의 output도 \(\vec v'_{t_c}\)와 비교하기에 이렇게 표현하는 것이 맞다.)

    이를 반영하면 다음과 같다.

     

    $$ P(t_c|\delta(in_j,f_s)) = P(\vec v'_{t_c}|\delta(in_j,f_s)) $$

    $$ = \frac{f(\vec v'_{t_c}, \delta (in_j, f_s))}{\sum ^D _d f(\vec v'_{t_d}, \delta(in_j,f_s))}$$

    $$f(\vec v'_{t_c}, \delta(in_j,f_s)) = Uh((\vec v'_{t_c}^T \times \delta(in_j, f_s))$$

    $$\text{D denotes the whole vocabulary constructed upon the repository RP}$$

    $$\text{Uh(.) denotes a sigmoid function applied to each value of a vector}$$

     

    이렇게해서, 결과적으로 softmax layout을 통과하는 것은 \((|D| + 1) \times 2 \times d \)개의 parameter이다. 

    이때, |D|가 asm instruction을 모두 고려해야 해서 값이 너무 크다보니 이를 줄이기 위해서 k negative sampling을 이용한다.

    k negative sampling을 고려해서 식을 계산하면 다음처럼 계산할 수 있다.

     

    $$log P(t_c|\delta(in_j,f_s)) \approx log f(\vec v'_{t_c} | \delta(in_j, f_s)) + \sum ^k_{i=1} \mathbb{E}_{t_d \backsim P_n(t_c)} \left( [[t_d \neq t_c]] log f(-1 \times \vec v'_{t_d}, \delta(in_j, f_s))\right) $$

    $$\text{[[.]] is an identify function}$$

    $$\mathbb{E}_{t_d \backsim P_n(t_c)} \text{ is an sampling function that samples a token }t_d\text{ from the vocabulary D } \\ \text{according to the noise distribution }P_n(t_c) \text{constructed from D}$$

     

    참고로, negative sampling을 이용하게 되면, target token과 연관있는 parameter에 대해서만 update를 하여 더욱 효율성을 높일 수 있다.

     

    이렇게 식을 세워서 feedback을 위해 derivatives를 계산하게 되면 각각 \(\vec v'_t\)와 \(\vec \theta_{f_s}\)에 대해 다음과 같이 나타낼 수 있다.

     

    잘.... 이해가 되지 않네요... 아마 유도과정 없이 결과만 써놔서 그런거 같긴한 데.... 그냥 그런갑다 해야할 거 같기도 합니다.

    각각의 미분값은 위와 같이 나오고, gradient를 위와 같이 계산할 수 있다. 

     

    여기까지 식으로 나타내게 되면, Training을 하는 데 필요한 것들을 모두 구한 것이다.

    구체적인 Training 알고리즘은 4.4.Training, Estimating and Searching에서 소개한다.

     

    4.3. Modeling Assmelby Functions

    이 section에서는 assembly functions을 multiple sequence로 나타내는 방법을 소개한다.

    Asm2Vec model에서 function은 보통 multiple sequences로 다루었다.

    즉, repository function \(f_s \in RP\)를 \(S(f_s) = seq[1:i]\)로 다루었다.

     

    그런데, CFG를 확인해보면 항상 linear한 CFG만 존재하는 것이 아니기에, 이를 linear하게 표현해야 하고,(그래서, 그 표현한 방법이 여러가지이기에 multiple sequence로 나타나는 듯) 그 방법을 이 장에서는 소개하고자 한다.

     

    4.3.1. Selective Callee Expansion

     

     

    Function inlining이란, 컴파일러가 바이너리를 컴파일하는 과정에서 function call 대신에 function body assembly를 그대로 삽입하는 최적화 방법중 하나이다. 

     

    Function inlining을 하게 되면 call instruction 대신에 function body instruction으로 대체되게 되는 데, 이는 CFG에 굉장히 많은 영향을 끼쳐서 clone search를 어렵게 만든다.

     

    BinGo라는 정적분석 Tool의 경우 선택적으로 선택적으로 Function Inlining을 시켜서 분석을 하게 된다. BinGo의 function inlining 방법을 Asm2Vec에 적용하여 multiple sequence를 더욱 다양하게 생성해서 coverage를 넓히고자 한다. 

     

    Asm2Vec에서는 다음과 규측으로 Function inlining을 한다.

     

    먼저, library call의 경우에는 inline하지 않는다. library call의 경우 token화가 잘 되어 있기 때문이다.

    둘째, first-order callee expand만 진행한다. BinGo의 경우 recursive하게 이를 진행하지만, 그럴 경우 처음 분석하려던 함수의 성질은 없어지고 callee의 성질이 강해져서 vector representation에 대해 좋지 않은 영향을 미치게 된다.

    셋째, 다음 식의 값이 0.01보다 작은 경우(임계값을 0.01로 하여)에 대해서 expansion한다.

    $$\alpha(f_c) = outdegree(f_c)/(outdegree(f_c) + indegree(f_c))$$

    넷째, 다음 식의 값이 0.6보다 작은 경우에 대해서 expansion한다.

    $$\delta(f_s,f_c) = length(f_c)/length(f_s)$$

    다섯째, 위 경우에 해당하지 않더라도, \(f_s\)의 길이가 10 line보다 작은 경우 expansion한다.

     

    위 규칙을 통해서 function inlining을 한 후 multi sequence를 생성한다.

     

    4.3.2. Edge Coverage

    edge를 random하게 sample해서 모든 edge를 sample할 때까지 각 edge에 대해서 instruction을 연결하여 새로운 sequence를 생성하는 방법

     

    4.3.3. Random Walk

    Random Walk를 통해서 CFG의 sequence를 생성하는 방법.

    Random walk를 이용하면, 보통 sequence의 길이가 edge coverage보다는 훨씬 길어진다. 

    하지만, 각각의 sequence들의 경우 실제로 CFG를 통해서 code execution이 진행될 수 있는 sequence들이고, 이를 통해서 basic block(기본이 되는 block)의 우선순위를 정하는 데도 도움이 될 수 있다. 

     

     

     

    위 소개한 방법들을 모두 종합하여 Multiple Sequence를 생성한다.

    구체적인 알고리즘은 4.4 Training, Estimating and Searching 에서 소개한다.

     

    4.4. Training, Estimating and Searching

    훈련 과정과 vector representation 계산 과정은 다음과 같다.

    각각의 알고리즘 모두 어렵지 않으니 천천히 읽어보며 이해해보는 것을 추천한다.

    훈련과정
    vector representation 계산 과정

    Experiment

    실험결과이다. 

    자세한 실험 중 설정한 변수 등은 논문을 참고하면 자세하게 나타나있고, 이 글에서는 어떤 실험을 하였고, 어떤 결과가 나왔는 지에 대해서만 간단하게 집고 넘어가고자 한다.

     

    실험은 총 4가지에 대해서 진행하였다.

    1. 최적화 옵션을 달리했을 때, Clone인지 판별하는 가?

    2. 난독화 솔루션을 적용했을 때, Clone인지 판별하는 가?

    3. 위에서 사용한 모든 binary에 대해서 실험을 할 때, Clone인지 판별하는 가?

    4. 알려진 취약점 dataset에 대해서 clone search가 가능한 가?

     

     

    5.1. Searching with Different Compiler Optimization Levels

    먼저 최적화 옵션을 다르게 한 경우에 대한 실험이다.

     

    아래 사진은 최적화 옵션을 다르게 했을 때, 함수간에 얼마나 차이가 나는 지 나타내는 것이다.

    이를 측정한 방법은 a)bytes가 얼마나 다른지 확인을 하였고, b) CFG가 얼마나 차이가 나는 지 확인하였다.

     

    아래 사진은 이를 시각화한 그래프이다.

     

    a)를 확인해보면, 최적화를 다르게 하였을 때, byte가 100% 동일한 경우는 아예 없었고, 평균적으로 O0최적화와 O3최적화를 비교하였을 때는 34.6%의 bytes에서 차이가 났고, O2와 O3를 비교하였을 때는 26.4%의 bytes에서 차이가 났다.

    b)를 확인해보면, 최적화를 다르게 하였을 때, CFG가 100% 동일한 경우는 O0 vs O3의 경우 17%, O2 vs O3의  있었고, 평균적으로 O0최적화와 O3최적화를 비교하였을 때는 82.7%의 차이가 났고, O2와 O3를 비교하였을 때는 40.4%의 차이가 났다.

     

    최적화를 다르게 할 경우 위와 같이 차이가 발생하는 데, clone search의 성능은 아래 표와 같았다.

    각 숫자의 경우, Clone search를 성공적으로 해낸 비율을 나타내고 대부분 Asm2Vec이 가장 좋은 성능을 냈다.

    O2,O3의 경우 94% 정확도를 자랑하고, O0,O3의 경우 80%의 정확도를 자랑했다.

     

    5.2. Searching with Different Compiler Optimization Levels

     

    난독화의 경우에는 위와 같이 차이가 나타났다. 주목할 만한 점은 FLA 난독화를 적용한 경우나 모두 적용하였을 때, CFG나 bytes 차이에서 크게 차이가 났다는 점을 볼 수 있다.

     

    이 경우에 대해서도 clone search 성능을 확인하였는 데,

    위 사진에서 확인할 수 있듯이, 대부분의 경우 Asm2Vec이 가장 좋은 성능을 보이는 것을 볼 수 있었다.

     

    5.3. Searching against All Binaries

    위 사진의 경우 5.1. 5.2.에서 사용한 모든 dataset에 대해서 실험을 진행하고, 결과를 시각화한 것이다.

    a)의 경우 top-k accuracy를 나타낸 것으로 가로축은 top-k의 k값이고, 세로축은 정확도이다.

    k값이 20일때 Asm2Vec은 70%의 recall, 즉 정확도를 가지고 target function을 return하였다. 이는 다른 방법들과 비교했을 때 압도적인 수치이다.

     

    b)의 경우 반대로 재현율에 대한 것이다.

    200개의 query를 날려서 재현을 얼마나 하는 지에 대해서 계산을 했다고 한다.

    그런데, 어떤것을 재현했는 지 논문에 정확하게 나타나 있지 않아서 헷갈리는 부분이 있다.

    하지만, 다른 방법들에 비해서 월등한 성능을 냈다는 것은 나타나 있다.

     

    c)는 vector의 크기(dimension의 크기)에 따라 sensitivity가 어떤 변화가 있는 지 나타내는 것이다.

     

     

    5.4. Searching Vulnerability Functions

    이제 취약점 탐지에 대한 실험도 진행을 하였는 데, 위 실험은 ESH dataset을 이용해서 진행을 하였다.

    이에 오탐율을 0에 모든 vulnability에 대해서 제대로 탐지를 해서 SOTA clone search 기법인 ESH와 비교하였을 때 outperform 하였다.

     

    또한, 추가적으로 각각의 취약함수에 대해서 난독화를 진행하였을 때도 잘 탐지하는 지 확인을 하였다.

    난독화는 3가지 방법으로 하였는 데, 위와 같이 난독화를 하였는 데도 제대로 취약함수인 것을 탐지하기도 하였다.

     

     

    6. Related Work

    논문에 간단히 나와있으니 읽어보는 걸 추천한다.

    7. Limitations and Conclusion

    한계점은 아래와 같다.

    1. 아직은 한가지 어셈블리에 대해서만 작동하며, cross architecture에 대해서는 고려하지 않았다.

    2. jump table처럼 동적 jump를 고려하지 못한다.

    3. Black box static approach이기에 반환된 결과에 대해서 설명을 하거나 symbolic equivalence에 대해서 증명을 하지 못한다.

     

    결론

    Asm2Vec은 아주 강력한 Clone search apporach 방법이다. 

    이는 assembly 함수에 대한 정보나 어셈블리에 대한 사전 지식을 전혀 필요로 하지 않고,

    모델 스스로 어셈블리 간의 관계를 학습하여 assembly function을 representation 한다.

    또한, 이 방법은 assembly function 이외에도 binary, fragment, basic blocks, function 등 assembly sequence의 여러 단위에 대해 적용 가능하다.

    최적화 옵션을 다르게 하거나, 난독화를 하였을 때도 Asm2Vec을 이용하면 Clone search를 해낼 수 있다는 점에서 아주 강력한 Clone search 방법이라는 것을 시사한다.

     


    이상으로 Asm2Vec 논문에 대한 리뷰를 마칩니다.

    꼼꼼히 하다 보니 굉장히 오래 걸렸는 데, 오히려 짧게 식과 그림 위주로 간단하게 소개하는 게 나았으려나 싶네요 ㅠㅠ..

     

    논문은 아래에서 확인 가능합니다.

    Reference

    IEEE Xplore : ieeexplore.ieee.org/document/8835340

    Paper : ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8835340

    Presentation Video : www.youtube.com/watch?v=6ethsho5uJA

     

    추가로 제가 논문 리딩하면서 메모했던 pdf파일 첨부합니다.

     

    08835340_memo.pdf
    1.40MB

    댓글