CTF 렐린지 도전
주어진 프로그램을 분석하고 플래그를 찾았다면 계속해서 새로운 문제를 풀이하는 CTF 챌린 지에 도전해 보자.
앞서 2장에서 학습했던 내용과 5장에서 배운 도구만으로 충분히 풀이할 수 있다.
각 문제풀이를 완료한 후에는 찾아낸 플래그를 oracle 프로그램에 입력함으로써 그다음 문제로 넘어갈 수 있다.
Level 2
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 84b34c124b2ba5ca224af8e33b077e9e
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 1 completed, unlocked lvl2 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
gdb main 함수
(gdb) x/20i 0x400500
=> 0x400500: sub rsp,0x8
0x400504: xor edi,edi
0x400506: call 0x4004d0 <time@plt>
0x40050b: mov edi,eax
0x40050d: call 0x4004c0 <srand@plt>
0x400512: call 0x4004e0 <rand@plt>
0x400517: cdq
0x400518: shr edx,0x1c
0x40051b: add eax,edx
0x40051d: and eax,0xf
0x400520: sub eax,edx
0x400522: cdqe
0x400524: mov rdi,QWORD PTR [rax*8+0x601060]
0x40052c: call 0x4004a0 <puts@plt>
0x400531: xor eax,eax
0x400533: add rsp,0x8
0x400537: ret
0x400538: nop DWORD PTR [rax+rax*1+0x0]
0x400540: xor ebp,ebp
0x400542: mov r9,rdx
(gdb)
// IDA HexRay
__int64 __fastcall main(int a1, char **a2, char **a3)
{
unsigned int v3; // eax
int v4; // eax
v3 = time(0LL);
srand(v3);
v4 = rand();
puts((&s)[v4 % 0x10]);
return 0LL;
}
C
복사
함수를 확인해보면 time함수 값으로 srand 시드 만들고, rand 함수로 값 생성하고 결과값의 &0xF (0x0 ~0xF)만 남겨서 rax값*8 + 0x601060의 주소값에 존재하는 스트링을 출력해줌
일단 베이스 주소인 0x601060을 확인하면 0x4006c4를 참조 하는걸 볼수있고
(gdb) x/20g 0x601060
0x601060: 0x00000000004006c4 0x00000000004006c7
0x601070: 0x00000000004006ca 0x00000000004006cd
0x601080: 0x00000000004006d0 0x00000000004006d3
0x601090: 0x00000000004006d6 0x00000000004006d9
0x6010a0: 0x00000000004006dc 0x00000000004006df
0x6010b0: 0x00000000004006e2 0x00000000004006e5
0x6010c0: 0x00000000004006e8 0x00000000004006eb
0x6010d0: 0x00000000004006ee 0x00000000004006f1
0x6010e0: 0x0000000000000000 0x0000000000000000
0x6010f0: 0x0000000000000000 0x0000000000000000
C
복사
해당 주소값을 확인해보면
(gdb) x/20s 0x00000000004006c4
0x4006c4: "03"
0x4006c7: "4f"
0x4006ca: "c4"
0x4006cd: "f6"
0x4006d0: "a5"
0x4006d3: "36"
0x4006d6: "f2"
0x4006d9: "bf"
0x4006dc: "74"
0x4006df: "f8"
0x4006e2: "d6"
0x4006e5: "d3"
0x4006e8: "81"
0x4006eb: "6c"
0x4006ee: "df"
0x4006f1: "88"
0x4006f4: "\001\033\003;0"
0x4006fa: ""
0x4006fb: ""
0x4006fc: "\005"
C
복사
뭔가 해쉬값이 보임. 해당 값을 플레그에 넣어보면 클리어
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 034fc4f6a536f2bf74f8d6d3816cdf88
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 2 completed, unlocked lvl3 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
Level3
readelf 로 봤을 때 파일 헤더가 많이 아파보입니다.
binary@binary-VirtualBox:~/code/chapter5$ readelf -a lvl3
ELF Header:
Magic: 7f 45 4c 46 02 01 01 0b 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: Novell - Modesto
ABI Version: 0
Type: EXEC (Executable file)
Machine: Motorola Coldfire
Version: 0x1
Entry point address: 0x4005d0
Start of program headers: 4022250974 (bytes into file)
Start of section headers: 4480 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
C
복사
xxd로 헤더부터 봅니다.
binary@binary-VirtualBox:~/code/chapter5$ xxd lvl3
00000000: 7f45 4c46 0201 010b 0000 0000 0000 0000 .ELF............
00000010: 0200 3400 0100 0000 d005 4000 0000 0000 ..4.......@.....
00000020: dead beef 0000 0000 8011 0000 0000 0000 ................
C
복사
딱봐도 DEADBEEF와 머신 값, OS 값이 정상적으로 쓰는 값이 아닙니다.
정상적으로 변경해줍니다.
binary@binary-VirtualBox:~/code/chapter5$ xxd lvl3
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 3e00 0100 0000 d005 4000 0000 0000 ..4.......@.....
00000020: 4000 0000 0000 0000 8011 0000 0000 0000 ................
C
복사
실행해봅니다
binary@binary-VirtualBox:~/code/chapter5$ ./lvl3
0e2ada7381d04d4d2ed31be82b121aa3 ./lvl3
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 0e2ada7381d04d4d2ed31be82b121aa3
Invalid flag: 0e2ada7381d04d4d2ed31be82b121aa3
C
복사
착하게 플래그를 뱉는줄 알았는데 아니었습니다.
다시 readelf로 lvl3 파일을 확인해본 결과
.text 섹션이 type이 이상합니다
binary@binary-VirtualBox:~/code/chapter5$ readelf -S --wide lvl3
There are 29 section headers, starting at offset 0x1180:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 000254 000020 00 A 0 0 4
[ 3] .note.gnu.build-id NOTE 0000000000400274 000274 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 000298 00001c 00 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002b8 0002b8 0000a8 18 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400360 000360 000081 00 A 0 0 1
[ 7] .gnu.version VERSYM 00000000004003e2 0003e2 00000e 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 00000000004003f0 0003f0 000040 00 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400430 000430 000018 18 A 5 0 8
[10] .rela.plt RELA 0000000000400448 000448 000078 18 AI 5 24 8
[11] .init PROGBITS 00000000004004c0 0004c0 00001a 00 AX 0 0 4
[12] .plt PROGBITS 00000000004004e0 0004e0 000060 10 AX 0 0 16
[13] .plt.got PROGBITS 0000000000400540 000540 000008 00 AX 0 0 8
[14] .text NOBITS 0000000000400550 000550 0001f2 00 AX 0 0 16
[15] .fini PROGBITS 0000000000400744 000744 000009 00 AX 0 0 4
[16] .rodata PROGBITS 0000000000400750 000750 00000c 00 A 0 0 4
[17] .eh_frame_hdr PROGBITS 000000000040075c 00075c 000034 00 A 0 0 4
[18] .eh_frame PROGBITS 0000000000400790 000790 000104 00 A 0 0 8
[19] .init_array INIT_ARRAY 0000000000600e10 000e10 000008 00 WA 0 0 8
[20] .fini_array FINI_ARRAY 0000000000600e18 000e18 000008 00 WA 0 0 8
[21] .jcr PROGBITS 0000000000600e20 000e20 000008 00 WA 0 0 8
[22] .dynamic DYNAMIC 0000000000600e28 000e28 0001d0 10 WA 6 0 8
[23] .got PROGBITS 0000000000600ff8 000ff8 000008 08 WA 0 0 8
[24] .got.plt PROGBITS 0000000000601000 001000 000040 08 WA 0 0 8
[25] .data PROGBITS 0000000000601040 001040 000010 00 WA 0 0 8
[26] .bss NOBITS 0000000000601050 001050 000008 00 WA 0 0 1
[27] .comment PROGBITS 0000000000000000 001050 000034 01 MS 0 0 1
[28] .shstrtab STRTAB 0000000000000000 001084 0000fc 00 0 0 1
C
복사
복구해줍시다
// section header starting offset 0x1180 + 0xe(numberofsection)+0x40(sectionheader size)
00001500 8D 00 00 00 08 00 00 00 06 00 00 00 00 00 00 00
00001500 8D 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00
C
복사
클리어
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 3A5C381E40D2FFFD95BA4452A0FB4A40
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 3 completed, unlocked lvl4 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
lvl4
//lvl4 hexray
_int64 __fastcall main(int a1, char **a2, char **a3)
{
__int64 i; // rax
__int64 v5[4]; // [rsp+0h] [rbp-38h] BYREF
char v6; // [rsp+20h] [rbp-18h]
unsigned __int64 v7; // [rsp+28h] [rbp-10h]
v7 = __readfsqword(0x28u);
v6 = 0;
v5[0] = 0x544A15120B72546ELL;
v5[1] = 0x5540501E0B055157LL;
v5[2] = 0x545D5C5C5154540BLL;
v5[3] = 0x691F5E0771171749LL;
for ( i = 0LL; i != 32; ++i )
*((_BYTE *)v5 + i) ^= byte_4006D8[i];
setenv("FLAG", (const char *)v5, 1);
return 0LL;
}
C
복사
setenv로 FLAG 값에 v5를 넣는걸로 확인됩니다.
setenv 함수에 bp를 걸고 v5값 (rsi)를 확인해봅시다.
binary@binary-VirtualBox:~/code/chapter5$ gdb ./lvl4
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./lvl4...(no debugging symbols found)...done.
(gdb) b *0x400524
Breakpoint 1 at 0x400524
(gdb) run
Starting program: /home/binary/code/chapter5/lvl4
Breakpoint 1, 0x0000000000400524 in ?? ()
(gdb) info reg
rax 0x20 32
rbx 0x0 0
rcx 0x0 0
rdx 0x1 1
rsi 0x7fffffffe370 140737488348016
rdi 0x400700 4196096
rbp 0x400650 0x400650
rsp 0x7fffffffe370 0x7fffffffe370
r8 0x4006c0 4196032
r9 0x7ffff7de7ab0 140737351940784
r10 0x846 2118
r11 0x7ffff7a2d740 140737348032320
r12 0x400550 4195664
r13 0x7fffffffe480 140737488348288
r14 0x0 0
r15 0x0 0
rip 0x400524 0x400524
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) x/20s $rsi
0x7fffffffe370: "656cf8aecb76113a4dece1688c61d0e7"
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 656cf8aecb76113a4dece1688c61d0e7
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 4 completed, unlocked lvl5 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
Level5
binary@binary-VirtualBox:~/code/chapter5$ ./lvl5
nothing to see here
binary@binary-VirtualBox:~/code/chapter5$
C
복사
여기선 안보인답니다. 싸가지가 없습니다.
0x400620에 디크립트 함수가 존재합니다.
main함수 호출 오프셋을 변조하고 파일을 다시 실행해봅니다.
binary@binary-VirtualBox:~/code/chapter5$ ./lvl5
key = 0x00400620
decrypted flag = 0fa355cbec64a05f7a5d050e836b1a1f
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 0fa355cbec64a05f7a5d050e836b1a1f
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 5 completed, unlocked lvl6 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
Level6
정상적으로 풀었고, 도저히 답이 안나와서 풀이를 봤으나 풀이에서도 동일하게 풀이함.
플래그도 동일 그러나 내 환경에서 클리어가 되지 않음
0x4006c1 주소값에 키값이 존재하고, 해당 주소를 확인해보면
2e29c64a0f03a6ee2a307fecc8c3ff42
값이 존재
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 2e29c64a0f03a6ee2a307fecc8c3ff42
Invalid flag: 2e29c64a0f03a6ee2a307fecc8c3ff42
2e29c64a0f03a6ee2a307fecc8c3ff42
C
복사
그러나 풀이를 확인하면 같은 상황이 발생
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 2e29c64a0f03a6ee2a307fecc8c3ff42
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 6 completed, unlocked lvl7 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
공식 링크에 있는 코드파일 다시 가져와서 하면 정상적으로 클리어가 가능하다.
binary@binary-VirtualBox:~/code/chapter5$ ./oracle 2e29c64a0f03a6ee2a307fecc8c3ff42
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 6 completed, unlocked lvl7 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint
C
복사
level7
lvl7를 압축풀면 2가지 파일이 나온다
binary@binary-VirtualBox:~/code/chapter5$ tar -zxvf lvl7
stage1
stage2.zip
C
복사
stage1에서 비번 찾은 다음 stage2 압축을 풀수있는 방식으로 되어있다.
stage1의 핵스값을 확인해보면
01 00 02 00 20 53 29 54 41 11 47 FA DE FF 45 32 .... S)TA.G...E2
20 4B 45 8A 59 00 00 00 01 1B 03 3B 34 00 00 00 KE.Y......;4...
STAGE2KEY를 추출할 수 있다
binary@binary-VirtualBox:~/code/chapter5$ unzip stage2.zip
Archive: stage2.zip
[stage2.zip] tmp password:
inflating: tmp
inflating: stage2
C
복사
stage2를 실행하면
파일의 전체 소스를 출력해준다.
```
0f25e512a7763eefb7696b3aeda1f964