1. objdump 우회하기
데이터 부분을 코드로 혼동하게 하거나 또는 그 반대로 속임으로써 objdump 도구를 우회하는 프로그램을 작성해 보자. 이를 성공하려면 인라인 어셈블리를 사용해야 될 수 있다.
// 테스트 코드
#include <stdio.h>
int main()
{
printf("Testing Break Assignment\n");
}
//objdump
objdump -d a.out
...
0000000000400526 <main>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: bf c4 05 40 00 mov $0x4005c4,%edi
40052f: e8 cc fe ff ff callq 400400 <puts@plt>
400534: b8 00 00 00 00 mov $0x0,%eax
400539: 5d pop %rbp
40053a: c3 retq
40053b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
...
C
복사
#include <stdio.h>
int main()
{
printf("Testing Break Assignment\n");
asm( ".byte 0xeb\n"
".byte 0x01\n"
".byte 0xe8\n");
}
binary@binary-VirtualBox:~/code/chapter6$ objdump -d a.out
...
0000000000400526 <main>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: bf c4 05 40 00 mov $0x4005c4,%edi
40052f: e8 cc fe ff ff callq 400400 <puts@plt>
400534: eb 04 jmp 400537 <main+0x11>
400536: b8 00 00 00 b8
00000000
00
5d c3 add %bl,-0x3d(%rbp)
40053e: 66 90 xchg %ax,%ax
binary@binary-VirtualBox:~/code/chapter6$ ./a.out
Testing Break Assignment
C
복사
위의 코드의 경우 3개의 바이트만 이용하여 alignment를 부순 모습이다.
0xeb(relative jump opcode), 0x01(offset)을 이용하여 해당 다음 실행 될 rip+ 0x01만큼 점프를 실행하였고,
점프되는 0x01바이트에 0xe8(call opcode)를 입력하여 alignment를 부수었다.
실제로 실행되는 코드는 위의 코드와 동일하다.
2. 재귀적 디스어셈블 도구 우회하기
1. 꼬리함수 호출
특히 함수 탐지 알고리즘을 우회 할 것이다.
//소스코드
#include <stdio.h>
void __iasm_function(void)
{
printf("Inner Assemble Printf Function\n");
__asm__ __volatile__(
"pop %rbp\n"
"pop %rbp\n"
"ret"
);
}
int main()
{
asm(
"mov $0x400526,%rax\n" //테스트를 위해 상수값으로 입력
"jmp *%rax\n"
".byte 0xc3");
}
//실행 결과
binary@binary-VirtualBox:~/code/chapter6$ ./a.out
Inner Assemble Printf Function
C
복사
정상적인 함수 아웃트로를 가지고 있지 않음. 또한 CFG이 정상적으로 그려지지 않음.
2. 다중 스위치문
#include <stdio.h>
int main()
{
int count;
scanf("%d",&count);
switch (count)
{
case 1:
return 1;
case 2:
return 2;
case 3:
return 3;
default:
return 0;
}
}
C
복사
다중 스위치문의 경우 아이다에서 정상적으로 표시해주는 것을 확인.
3. 함수 탐지 기능 개선하기
개인적인 의견
꼬리 함수 호출에 대해서는 (간접 호출) 거의 무조건 동적으로 확인을 해야한다고 생각하고
스위치 문은 아이다에서 해결된 부분이라고 생각함.
함수 형식을 비틀려면 어셈블리로 함수 전체를 작성하거나, 패킹되어 있는 바이너리를 얼마나 상세히 분석하냐가 중요한데, 해당 함수 앞뒤 연관관계 없이 분석하기에는 너무 오탐 가능성이 높아 정적으로만 해결할 부분은 아니라고 생각함.