Posts LLVM - 가상화 난독화를 수행하는 pass 제작 (2/4)
Post
Cancel

LLVM - 가상화 난독화를 수행하는 pass 제작 (2/4)

이번 목표 - 가상화 난독화를 수행하는 pass 작성하기

  • 패스 생성 준비
  • 필요한 변수 삽입

깃허브 소스코드 ✨

이번 주부터 가상화 난독화를 해 볼 것인데, 우선 switch문을 넣는 것을 해 보기로 했다. 입력 C파일은 저번에 사용한 것을 조금 고쳐 사용했다. virtualTest.c

일단 일반적인 코드에 적용할 수 있는 게 아닌, 이 코드만 난독화할 수 있게 한 다음에 일반적이게 고칠 생각!!

설명을 위해 작성한 코드는 이후에 변경된 것이 많아, 위의 깃허브 링크에서 확인하는 것이 좋음!

1. Pass 생성 및 바이트코드 확인

새로운 Pass를 “VirtualEditor”라는 이름으로 생성해 두었다. 그 후 저번 글에서 난독화했던 방법을 적용하기 위해, 원본 C코드와 임의로 난독화한 C코드의 바이트코드를 확인해 본다.

난독화 전

img

난독화 후

img

main은 달라진 것이 없으니, 이름이 main이 아닌 함수에서만 난독화를 하도록 해야겠다.

2. return값 저장하기 위한 변수와 for문을 위한 i allocate하기

우선 난독화를 하면서 더 추가해줘야 할 부분이 있다.

img

해당 부분을 추가해주어야 하는데, 변수를 할당해주는 것이 생각보다 어려워서(?) 헤메다 알아냈다ㅠㅠ AllocaInst를 사용할 수 있지만 IRBuilder를 이용해보고 싶어서, 빌더를 이용하는 방법으로 작성해봤다. 변수를 할당하기 위해서는 IRBuilder를 추가해주고 해당 변수의 타입을 넣고 CreateAlloca를 이용하면 된다.

1
2
3
IRBuilder<> builder(entry_bb);

Value *v = builder.CreateAlloca(builder.getInt32Ty());

문제는 이렇게 작성하면 entry_bb의 마지막에 추가하게 된다……
그래서 그냥 split_point을 이용해 앞부분에 빈 BasicBlock을 하나 생성해주고 그 BasicBlock에 변수 할당하는 것을 추가한 뒤, 분기문을 삭제하고 다시 추가하는 복잡한(…) 방식으로 했다. 이것도 나중에 발전시킬 수 있으면 바꿔 봐야지..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BasicBlock::iterator split_point =
    (BasicBlock::iterator)entry_bb->getFirstNonPHIOrDbgOrLifetime();
BasicBlock *original_entry_bb =
    entry_bb->splitBasicBlock(split_point, "originEntry");
// 할당할 변수들을 넣을 공간 생성

IRBuilder<> builder(entry_bb);
Value *var = builder.CreateAlloca(builder.getInt32Ty());
Value *var_2 = builder.CreateAlloca(builder.getInt32Ty());
// retval, i에 해당하는 변수 할당

BranchInst::Create(original_entry_bb, entry_bb);
BasicBlock::iterator to_remove = entry_bb->begin();
Instruction *inst_to_remove = &(*to_remove);
inst_to_remove->dropAllReferences();
inst_to_remove->eraseFromParent();
// entry_bb의 끝에 분기문을 넣어주고 원래 있던 분기문을 삭제

이렇게 변수 할당이 끝난다. 이번에는 i 변수에 0을 저장해주어야 한다.

1
2
Value *value_0 = Constant::getNullValue(builder.getInt32Ty());
StoreInst *store_inst = new StoreInst(value_0, var_i, entry_bb);

상수 0을 만들어 주고, store instruction을 생성하여 i변수에 0값을 넣어준다.

.

-여기까지 retval, i변수 할당하고 i에 초기값 0 넣어주는 코드-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
BasicBlock::iterator split_point =
    (BasicBlock::iterator)entry_bb->getFirstNonPHIOrDbgOrLifetime();
BasicBlock *original_entry_bb =
    entry_bb->splitBasicBlock(split_point, "originEntry");
// 할당할 변수들을 넣을 공간 생성

IRBuilder<> builder(entry_bb);
Value *var_retval = builder.CreateAlloca(builder.getInt32Ty());
Value *var_i = builder.CreateAlloca(builder.getInt32Ty());
// retval, i에 해당하는 변수 할당

Value *value_0 = Constant::getNullValue(builder.getInt32Ty());
StoreInst *store_inst = new StoreInst(value_0, var_i, entry_bb);
// i 변수에 0값 넣어줌

BranchInst::Create(original_entry_bb, entry_bb);
BasicBlock::iterator to_remove = entry_bb->begin();
Instruction *inst_to_remove = &(*to_remove);
inst_to_remove->dropAllReferences();
inst_to_remove->eraseFromParent();
// entry_bb의 끝에 분기문을 넣어주고 원래 있던 분기문을 삭제

추가된 결과 화면

img

.

+ store instruction을 생성하면서 알았는데,

1
StoreInst *store_inst = new StoreInst(value_0, var_i, entry_bb);

와 같은 코드에서 entry_bb 부분에 nullptr을 넣어 준 뒤,

1
store_inst->insertAfter(inst);

와 같은 코드로 store instruction을 마음대로 원하는 곳(inst 앞)에 넣어줄 수 있다. (처음에 branch instruction만들 때 고민했던 위치 문제를 이 방법으로 해결할 수 있을 것 같다) 나중에 이용해보자.

다음 글에 계속 »

This post is licensed under CC BY 4.0 by the author.

Contents