csapp学习-binbomb

本文最后更新于:2 年前

就说,有 6 关,每关都不一样那种, 然后自己慢慢整出来就行

给了一个 c 代码和 elf 可执行程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/***************************************************************************
* 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;
}

第一关:

字符串比较

img

Border relations with Canada have never been better.

第二关:

img

第三关:

img

如代码所示 : 0 207 是一组 1 311 是一组 , 依次递推,拿出一组即可

第四关:

img

img

一开始,我真以为是递归函数,后来我才发现,我太年轻了,

img

所以,这里 的答案应该是

7 0

第五关:

img

1
2
3
4
5
6
7
8
# coding = utf-8 
table = 'maduiersnfotvbyl'
s = "flyers"
flag = ''
for i in s:
flag += chr(96 + table.index(i))

print(flag)

这里 96 要符合 &0xf = 0

ionefg 即可

剩下的慢慢整

2021.4.16 还差两关

第六关和 boss 关

好吧,我承认,后面的超出了我的能力范围

2021.4.22 补充

第六关

是一个 单向链表

1
2
3
4
5
struct LinkedList{
int value;
int num;
struct LinkedList* next;
}

ida 套上结构体, 进行逆向, 发现有的地方还是 没反编译明白, 这就很难办了。

直接 读汇编, 我本身是很抗拒读汇编的, 太依赖 ida 的f5了, 哭了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
__int64 __fastcall phase_6(__int64 a1)
{
int *v1; // r13
int v2; // er12
int v3; // ebx
int *v4; // rax
unsigned __int64 i; // rsi
LinkedList *v6; // rdx
int v7; // eax
int v8; // ecx
LinkedList *v9; // rbx
LinkedList v10; // rax
LinkedList *j; // rcx
int v12; // ebp
__int64 result; // rax
int v14[6]; // [rsp+0h] [rbp-78h] BYREF
int v15; // [rsp+18h] [rbp-60h] BYREF
LinkedList v16; // [rsp+20h] [rbp-58h] BYREF
char v17; // [rsp+50h] [rbp-28h] BYREF

v1 = v14;
read_six_numbers(a1, v14);
v2 = 0;
while ( 1 ) // 判断 是否有没有 重复 数字
{
if ( (*v1 - 1) > 5 )
explode_bomb();
if ( ++v2 == 6 )
break;
v3 = v2;
do
{
if ( *v1 == v14[v3] )
explode_bomb();
++v3;
}
while ( v3 <= 5 );
++v1;
}
v4 = v14; // 一个加密, 7- 真正的位置 = 应输入的位置
do
{
*v4 = 7 - *v4;
++v4;
}
while ( v4 != &v15 );
for ( i = 0LL; i != 24; i += 4LL ) // 按照输入的每个数字进行排序
{
v8 = v14[i / 4];
if ( v8 <= 1 )
{
v6 = &node1;
}
else
{
v7 = 1;
v6 = &node1;
do
{
v6 = v6->next;
++v7;
}
while ( v7 != v8 );
}
*(&v16.value + 2 * i) = v6;
}
v9 = *&v16.value;
*&v10.value = &v16.next;
for ( j = *&v16.value; ; j = v10.next ) // 链表重新排序
{
v10.next = **&v10.value;
j->next = **&v10.value;
*&v10.value += 8LL;
if ( *&v10.value == &v17 )
break;
}
v10.next->next = 0LL;
v12 = 5;
do // 链表数值比较, 对链表的数值进行比较, 从大到小
{
result = v9->next->value;
if ( v9->value < result )
explode_bomb();
v9 = v9->next;
--v12;
}
while ( v12 );
return result;
}

链表数据

img

0x14c:1 0xa8:2 0x39c:3 0x283:4 0x1dd:5 0x1bb:6

从大到小排序后

3 4 5 6 1 2

经过 y=7-x 加密后, 最终答案为

4 3 2 1 6 5

所以前六关的答案是

1
2
3
4
5
6
Border relations with Canada have never been better.
1 2 4 8 16 32
1 311
7 0
ionefg
4 3 2 1 6 5

隐藏关卡

boss 好激动

这一关的打开方式很奇葩, 是一个写死的地址, 格式化字符串,判断是否有特定的字符串

这个地址,我调试了一下,发现 和第四关的数据非常的像

img

测试了一下,发现 , 写死的地址就是第四关的地址,

img

所以直接 , 在第四关输入后面加一个 字符串 即可打开 boss 关卡

二叉树逆向

img

一个递归函数, 计算数据, 是否满足条件

img

这一题 , 第一眼看到就是那啥, 直接爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# coding=utf-8
import subprocess

def fuck(num):
with open('test1.txt', mode='w') as f:
with open('test.txt', mode='r') as f1:
content = f1.read()
f.write(content + '\n' + str(num))
s = subprocess.Popen(['./bomb','test1.txt'], stdout=subprocess.PIPE)
content = s.stdout.read().decode()
if "You've defused the secret" in content:
print(num)

for i in range(1000):
fuck(i)

最后比较气人的是, 我这边 输入三位,其实程序只能读到 两位数, 还好答案只是两位数, 勉强过了。

img

答案是 20 或者 22

img

总结

二进制炸弹锻炼了 反汇编能力, 也反映出了我自身的不足, 沉不住气, 不能静下心来 阅读反汇编代码。

总结一句话,懒狗是我没错了

本文所用附件

1
2
3
链接:https://pan.baidu.com/s/1pGqpQLGa-erpLJSTvPguDQ 
提取码:1234
复制这段内容后打开百度网盘手机App,操作更方便哦

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!