대부분 디스어셈블러와 디버거를 이용하여 취약점을 분석하거나 내부 보안로직을 우회하는 등 프로그램에 대한 공격을 수행하게 됩니다.
오늘은 간단한게, Binary 파일 분석을 통해서 어플리케이션의 취약, 인증 우회 포인트를 찾는 방법에 대해 이야기할까 합니다.
대부분의 프로그램들은 매우 잘 만들어져 Binary 분석은 커녕 리버싱 자체로도 벅찬 경우가 있지만, 또 반대로 간단하게 Binary 분석을 통해 쉽게 풀어나갈 수 있는 프로그램도 있습니다.
아래 코드는 간단하게 Password 를 받아 비교하여, 결과를 주는 코드입니다.
코드를 보시면 알겠지만, strcmp 사용으로 취약할 수 있고, 단순한 코드여서 assemble를 통해 흐름을 바꾸어 쉽게 변조가 가능한 프로그램입니다.
#include <stdio.h>
#define db_id "admin"
#define db_pw "admin123"
void main()
{
char user_pw[644];
printf("input PW: ");scanf("%s",user_pw);
if(!strcmp(db_pw,user_pw))
{
printf("\nOK Admin..\n");
}
else
{
printf("\nPW Error.\n");
}
}
또한 추가로 간단한 문제점이 하나 있는데, 바로 #define을 사용하여 Password 값을 저장하고 있는 것 입니다.
프로그램 내 인증이나, 패스워드 등 중요한 데이터를 포함하고 있을 경우 hex editor로 확인이 가능합니다.
물론 ... 간단한 코드이기에 확인이 쉬운 것 뿐이지 큰 프로그램은 Binary로 분석하기 어렵습니다..ㅎㅎㅎㅎㅎㅎㅎㅎ
Test Code Compile & Execute
일단 테스트를 위해 컴파일합니다.
# gcc -o define_code define_code.c
# ll
합계 20
..snip..
-rwxr-xr-x 1 root root 7287 11월 21 00:23 define_code
-rw-r--r-- 1 root root 251 11월 21 00:23 define_code.c
실행하면 아래와 같이 Password를 물어보고, 맞으면 OK Admin, 틀리면 PW Error를 노출하게 됩니다.
# ./define_code
input PW: www.codeblack.net
PW Error.
gHex(or hxd)를 통한 분석(Binary Analysis with HEX Editor)
ghex를 통해 한번 열어서 확인해보겠습니다. (윈도우에서는 대표적으로 hxd가 많이 사용되지요)
ELF로 시작하는 실행 파일입니다.
여기서 노출되었던 문자열 위주로 찾으면 조금 편합니다.
"PW Error" 문자열 기준으로 검색해시면 아래와 같이 찾아낼 수 있습니다. (다 쓰기보단 나눠서 찾는게 좋아요)
찾아낸 PW Error 문자열 주변으로 PW가 맞았을 때 메시지와 아까 우리가 지정한 Password 문자열을 확인할 수 있습니다.
물론 코드를 모르는 상태에서 보면 저게 뭔가 싶겠지만, 스크립트를 짜서 나름대로 분석하거나, 노가다를 통해서 어느정도 유추할 수 있는 부분이기에 프로그램 입장에서는 취약한 포인트를 하나 더 가지고 있는 상태입니다.
저련 형태로 단순 코딩된 데이터는 hex editor 이외에도 여러가지 툴들을 이용해 좀 더 쉽게 확인할 수 있습니다.
# objdump -d define_code
000000000040060c <main>:
40060c: 55 push %rbp
40060d: 48 89 e5 mov %rsp,%rbp
400610: 48 81 ec 90 02 00 00 sub $0x290,%rsp
400617: bf 1c 07 40 00 mov $0x40071c,%edi
40061c: b8 00 00 00 00 mov $0x0,%eax
400621: e8 9a fe ff ff callq 4004c0 <printf@plt>
400626: 48 8d 85 70 fd ff ff lea -0x290(%rbp),%rax
40062d: 48 89 c6 mov %rax,%rsi
400630: bf 27 07 40 00 mov $0x400727,%edi
400635: b8 00 00 00 00 mov $0x0,%eax
40063a: e8 b1 fe ff ff callq 4004f0 <__isoc99_scanf@plt>
40063f: 48 8d 85 70 fd ff ff lea -0x290(%rbp),%rax
400646: 48 89 c6 mov %rax,%rsi
400649: bf 2a 07 40 00 mov $0x40072a,%edi
40064e: e8 8d fe ff ff callq 4004e0 <strcmp@plt>
400653: 85 c0 test %eax,%eax
400655: 75 0c jne 400663 <main+0x57>
400657: bf 33 07 40 00 mov $0x400733,%edi
40065c: e8 4f fe ff ff callq 4004b0 <puts@plt>
400661: eb 0a jmp 40066d <main+0x61>
400663: bf 3f 07 40 00 mov $0x40073f,%edi
400668: e8 43 fe ff ff callq 4004b0 <puts@plt>
strcmp 이후에 바로 jne, jmp가 있는 구간이 확인되고, 흐름을 바꾼다면 쉽게 가짜 패스워드로 통과할 수 있겠지요. :)
(gdb) set disassembly intel
(gdb) disas main
Dump of assembler code for function main:
0x000000000040060c <+0>: push rbp
0x000000000040060d <+1>: mov rbp,rsp
0x0000000000400610 <+4>: sub rsp,0x290
0x0000000000400617 <+11>: mov edi,0x40071c
0x000000000040061c <+16>: mov eax,0x0
0x0000000000400621 <+21>: call 0x4004c0 <printf@plt>
0x0000000000400626 <+26>: lea rax,[rbp-0x290]
0x000000000040062d <+33>: mov rsi,rax
0x0000000000400630 <+36>: mov edi,0x400727
0x0000000000400635 <+41>: mov eax,0x0
0x000000000040063a <+46>: call 0x4004f0 <__isoc99_scanf@plt>
0x000000000040063f <+51>: lea rax,[rbp-0x290]
0x0000000000400646 <+58>: mov rsi,rax
0x0000000000400649 <+61>: mov edi,0x40072a
0x000000000040064e <+66>: call 0x4004e0 <strcmp@plt>
0x0000000000400653 <+71>: test eax,eax
0x0000000000400655 <+73>: jne 0x400663 <main+87>
0x0000000000400657 <+75>: mov edi,0x400733
0x000000000040065c <+80>: call 0x4004b0 <puts@plt>
0x0000000000400661 <+85>: jmp 0x40066d <main+97>
0x0000000000400663 <+87>: mov edi,0x40073f
0x0000000000400668 <+92>: call 0x4004b0 <puts@plt>
0x000000000040066d <+97>: leave
0x000000000040066e <+98>: ret
HAHWULSecurity engineer, Gopher and H4cker! |
0 개의 댓글:
Post a Comment