두번째 과제인 Bomb lab: Defusing a Binary Bomb의 풀이 과정을 정리한다. 보고서 작성도 있어서 겸사겸사 정리
우선 bomb.tar을 다운로드 받아 리눅스 서버에서 압축 해제하고 bomb.c파일을 열어보았다.
/***************************************************************************
* Dr. Evil's Insidious Bomb, Version 1.1
* Copyright 2011, Dr. Evil Incorporated. All rights reserved.
*
* LICENSE:
*
* Dr. Evil Incorporated (the PERPETRATOR) hereby grants you (the
* VICTIM) explicit permission to use this bomb (the BOMB). This is a
* time limited license, which expires on the death of the VICTIM.
* The PERPETRATOR takes no responsibility for damage, frustration,
* insanity, bug-eyes, carpal-tunnel syndrome, loss of sleep, or other
* harm to the VICTIM. Unless the PERPETRATOR wants to take credit,
* that is. The VICTIM may not distribute this bomb source code to
* any enemies of the PERPETRATOR. No VICTIM may debug,
* reverse-engineer, run "strings" on, decompile, decrypt, or use any
* other technique to gain knowledge of and defuse the BOMB. BOMB
* proof clothing may not be worn when handling this program. The
* PERPETRATOR will not apologize for the PERPETRATOR's poor sense of
* humor. This license is null and void where the BOMB is prohibited
* by law.
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "support.h"
#include "phases.h"
/*
* Note to self: Remember to erase this file so my victims will have no
* idea what is going on, and so they will all blow up in a
* spectaculary fiendish explosion. -- Dr. Evil
*/
FILE *infile;
int main(int argc, char *argv[])
{
char *input;
/* Note to self: remember to port this bomb to Windows and put a
* fantastic GUI on it. */
/* When run with no arguments, the bomb reads its input lines
* from standard input. */
if (argc == 1) {
infile = stdin;
}
/* When run with one argument <file>, the bomb reads from <file>
* until EOF, and then switches to standard input. Thus, as you
* defuse each phase, you can add its defusing string to <file> and
* avoid having to retype it. */
else if (argc == 2) {
if (!(infile = fopen(argv[1], "r"))) {
printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]);
exit(8);
}
}
/* You can't call the bomb with more than 1 command line argument. */
else {
printf("Usage: %s [<input_file>]\n", argv[0]);
exit(8);
}
/* Do all sorts of secret stuff that makes the bomb harder to defuse. */
initialize_bomb();
printf("Welcome to my fiendish little bomb. You have 6 phases with\n");
printf("which to blow yourself up. Have a nice day!\n");
/* Hmm... Six phases must be more secure than one phase! */
input = read_line(); /* Get input */
phase_1(input); /* Run the phase */
phase_defused(); /* Drat! They figured it out!
* Let me know how they did it. */
printf("Phase 1 defused. How about the next one?\n");
/* The second phase is harder. No one will ever figure out
* how to defuse this... */
input = read_line();
phase_2(input);
phase_defused();
printf("That's number 2. Keep going!\n");
/* I guess this is too easy so far. Some more complex code will
* confuse people. */
input = read_line();
phase_3(input);
phase_defused();
printf("Halfway there!\n");
/* Oh yeah? Well, how good is your math? Try on this saucy problem! */
input = read_line();
phase_4(input);
phase_defused();
printf("So you got that one. Try this one.\n");
/* Round and 'round in memory we go, where we stop, the bomb blows! */
input = read_line();
phase_5(input);
phase_defused();
printf("Good work! On to the next...\n");
/* This phase will never be used, since no one will get past the
* earlier ones. But just in case, make this one extra hard. */
input = read_line();
phase_6(input);
phase_defused();
/* Wow, they got it! But isn't something... missing? Perhaps
* something they overlooked? Mua ha ha ha ha! */
return 0;
}
총 6단계의 phase로 구성되며 각 phase마다 정답을 찾아내 입력해야 한다. read_line()함수가 정답을 입력받고, 각 phase함수에 argument로 전달되어 정답과 일치하면 phase_defused함수를 통해 폭탄이 해제되는 것 같다. 한번 틀릴 때마다 점수가 1/2씩 감점되니 신중하게 찾아낼 필요가 있다.
objdump -d bomb
위 명령어를 입력하면 deassemble된 코드가 출력된다.
bomb: file format elf64-x86-64
Disassembly of section .init:
0000000000000e18 <_init>:
e18: 48 83 ec 08 sub $0x8,%rsp
e1c: 48 8b 05 c5 31 20 00 mov 0x2031c5(%rip),%rax # 203fe8 <__gmon_start__>
e23: 48 85 c0 test %rax,%rax
e26: 74 02 je e2a <_init+0x12>
e28: ff d0 callq *%rax
e2a: 48 83 c4 08 add $0x8,%rsp
e2e: c3 retq
Disassembly of section .plt:
0000000000000e30 <.plt>:
e30: ff 35 ba 30 20 00 pushq 0x2030ba(%rip) # 203ef0 <_GLOBAL_OFFSET_TABLE_+0x8>
e36: ff 25 bc 30 20 00 jmpq *0x2030bc(%rip) # 203ef8 <_GLOBAL_OFFSET_TABLE_+0x10>
e3c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000000e40 <getenv@plt>:
e40: ff 25 ba 30 20 00 jmpq *0x2030ba(%rip) # 203f00 <getenv@GLIBC_2.2.5>
e46: 68 00 00 00 00 pushq $0x0
e4b: e9 e0 ff ff ff jmpq e30 <.plt>
0000000000000e50 <strcasecmp@plt>:
e50: ff 25 b2 30 20 00 jmpq *0x2030b2(%rip) # 203f08 <strcasecmp@GLIBC_2.2.5>
e56: 68 01 00 00 00 pushq $0x1
e5b: e9 d0 ff ff ff jmpq e30 <.plt>
.
.
.
너무 길고 복잡하기도 하니 다음과 같이 텍스트 파일로 저장하려 했으나 과제 서버가 지원하는 objdump 버전에서는 --visualize-jumps 옵션이 제공되지 않는 것 같다. jump instruction을 시각적으로 보여주는 옵션인데 생으로 할 수밖에 없는 상황.
objdump -d --visualize-jumps bomb > bomb_disassembled.txt
어쩔 수 없이 objdump -d bomb > bomb_disassembled.txt만 실행해서 파일을 저장한다. 그리고 scp 명령어를 사용해 로컬 파일로 다운로드해주었다.
scp -P 2222<user_id>@<server_address>:~/bomb20/bomb_disassembled.txt <download_path>
먼저 main함수를 확인해본다.
0000000000001489 <main>:
1489: f3 0f 1e fa endbr64
148d: 53 push %rbx
148e: 83 ff 01 cmp $0x1,%edi
1491: 0f 84 f8 00 00 00 je 158f <main+0x106>
1497: 48 89 f3 mov %rsi,%rbx
149a: 83 ff 02 cmp $0x2,%edi
149d: 0f 85 21 01 00 00 jne 15c4 <main+0x13b>
14a3: 48 8b 7e 08 mov 0x8(%rsi),%rdi
14a7: 48 8d 35 e2 20 00 00 lea 0x20e2(%rip),%rsi # 3590 <array.3473+0x410>
14ae: e8 5d fe ff ff callq 1310 <fopen@plt>
14b3: 48 89 05 f6 41 00 00 mov %rax,0x41f6(%rip) # 56b0 <infile>
14ba: 48 85 c0 test %rax,%rax
14bd: 0f 84 df 00 00 00 je 15a2 <main+0x119>
.
.
.
main함수에서는 실행과 관련된 코드만 존재한다.
문제를 풀기 전에 다음과 같이 데이터를 추출해본다.
objdump -s -j .rodata bomb > bomb_rodata.txt
읽기 전용 데이터를 저장한다. .rodata 섹션에는 주로 문자열 상수 등의 데이터가 저장된다.
그리고 다음과 같이 초기화된 전역변수와 static 변수를 포함하는 섹션 .data도 저장한다.
objdump -s -j .data bomb > bomb_data.txt
마찬가지로 로컬 파일로 저장해주었다.
.rodata 섹션
bomb: file format elf64-x86-64
Contents of section .rodata:
3000 01000200 25733a20 4572726f 723a2043 ....%s: Error: C
3010 6f756c64 6e277420 6f70656e 2025730a ouldn't open %s.
3020 00557361 67653a20 2573205b 3c696e70 .Usage: %s [<inp
3030 75745f66 696c653e 5d0a0054 68617427 ut_file>]..That'
3040 73206e75 6d626572 20322e20 204b6565 s number 2. Kee
3050 7020676f 696e6721 0048616c 66776179 p going!.Halfway
3060 20746865 72652100 476f6f64 20776f72 there!.Good wor
3070 6b212020 4f6e2074 6f207468 65206e65 k! On to the ne
3080 78742e2e 2e000000 57656c63 6f6d6520 xt......Welcome
3090 746f206d 79206669 656e6469 7368206c to my fiendish l
.
.
.
.data 섹션
bomb: file format elf64-x86-64
Contents of section .data:
5000 00000000 00000000 08500000 00000000 .........P......
5010 28000000 00000000 00000000 00000000 (...............
5020 00000000 00000000 00000000 00000000 ................
5030 01000000 00000000 00000000 00000000 ................
5040 00000000 00000000 00000000 00000000 ................
5050 63000000 00000000 00000000 00000000 c...............
5060 00000000 00000000 00000000 00000000 ................
5070 23000000 00000000 00000000 00000000 #...............
5080 00000000 00000000 00000000 00000000 ................
5090 07000000 00000000 00000000 00000000 ................
.
.
.
여기에는 아직은 알 수 없는 데이터가 존재한다.
'ComputerSystemProgramming' 카테고리의 다른 글
[컴퓨터시스템프로그래밍] CS:APP Bomb lab: Defusing a Binary Bomb (5) phase_4 (0) | 2024.11.11 |
---|---|
[컴퓨터시스템프로그래밍] CS:APP Bomb lab: Defusing a Binary Bomb (4) phase_3 (0) | 2024.11.09 |
[컴퓨터시스템프로그래밍] CS:APP Bomb lab: Defusing a Binary Bomb (3) phase_2 (0) | 2024.11.09 |
[컴퓨터시스템프로그래밍] CS:APP Bomb lab: Defusing a Binary Bomb (2) phase_1 (0) | 2024.11.08 |
[컴퓨터시스템프로그래밍] CS:APP Data lab bits.c Solution (3) | 2024.10.12 |