Computing 101

Computers run an incredible managerie of programs that make modern life possible. But how do they work, deep down inside? In this dojo, we will dive into the depths of computation, reach (something close to) its very underpinnings, and strive to understand it all.

Your First Program

Software Introspection

Computer Memory

Hello Hackers

Assembly Crash Course

Debugging Refresher

A critical part of working with computing is understanding what goes wrong when something inevitably does. This module will build on your prior exposure to GDB with some more debugging of programs: digging in, poking around, and gaining knowledge. This is one of the most critical skills that you will learn in your computing journey, and this module will hopefully help water the seed that we planted before.

As you know, GDB is a very powerful dynamic analysis tool which you can use in order to understand the state of a program throughout its execution. You will become more familiar with some of its capabilities in this module.

level 4

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
#coding: utf-8

from pwn import *

# context.log_level = 'debug'

p = process('/challenge/embryogdb_level4')
p.recvuntil(b'(gdb)')
p.sendline(b"set style enabled off")
p.recvuntil(b"(gdb)")
p.sendline(b"r")
p.recvuntil(b"(gdb)")

p.sendline(b"b *($pc+0x38)")
p.recvuntil(b"(gdb)")
p.sendline(b"c")
for i in range(0, 4):
p.recvuntil(b"(gdb)")
p.sendline(b"x/gx $rbp-0x18")
secret = p.recvline().decode()
secret = secret.split("\t")[1].strip()
p.recvuntil(b"(gdb)")
print("secret => ", secret)
p.sendline(b"c")
p.recvuntil(b"Random value: ")
p.sendline(secret.encode())

p.recvuntil(b"flag:\n")
flag = p.recvline().decode()
print("flag => ", flag)

p.close()

level 5

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
#coding: utf-8

from pwn import *

# context.log_level = 'debug'

p = process('/challenge/embryogdb_level5')
p.recvuntil(b'(gdb)')
p.sendline(b"set style enabled off")
p.recvuntil(b"(gdb)")
p.sendline(b"r")
p.recvuntil(b"(gdb)")

p.sendline(b"b *(main+709)")
p.recvuntil(b"(gdb)")
p.sendline(b"c")
for i in range(0, 8):
p.recvuntil(b"(gdb)")
p.sendline(b"x/gx $rbp-0x18")
secret = p.recvline().decode()
secret = secret.split("\t")[1].strip()
p.recvuntil(b"(gdb)")
print("secret => ", secret)
p.sendline(b"c")
p.recvuntil(b"Random value: ")
p.sendline(secret.encode())

p.recvuntil(b"flag:\n")
flag = p.recvline().decode()
print("flag => ", flag)

p.close()

level 6

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
#coding: utf-8

from pwn import *

# context.log_level = 'debug'

p = process('/challenge/embryogdb_level6')
p.recvuntil(b'(gdb)')
p.sendline(b"set style enabled off")
p.recvuntil(b"(gdb)")
p.sendline(b"r")
p.recvuntil(b"(gdb)")

p.sendline(b"b *(main+577)")
p.recvuntil(b"(gdb)")
p.sendline(b"c")
for i in range(0, 64):
p.recvuntil(b"(gdb)")
p.sendline(b"x/gx $rbp-0x18")
secret = p.recvline().decode()
secret = secret.split("\t")[1].strip()
p.recvuntil(b"(gdb)")
print("secret => ", secret)
p.sendline(b"c")
p.recvuntil(b"Random value: ")
p.sendline(secret.encode())

p.recvuntil(b"flag:\n")
flag = p.recvline().decode()
print("flag => ", flag)

p.close()

level 7

1
2
r
call (void)win()

level 8

1
2
3
4
r
x/40i win
set $rip=win+35
c

根据 win 的内容:

1
2
3
4
5
6
7
8
9
10
11
0x0000564afe32d951 <+0>:	endbr64 
0x0000564afe32d955 <+4>: push %rbp
0x0000564afe32d956 <+5>: mov %rsp,%rbp
0x0000564afe32d959 <+8>: sub $0x10,%rsp
0x0000564afe32d95d <+12>: movq $0x0,-0x8(%rbp)
0x0000564afe32d965 <+20>: mov -0x8(%rbp),%rax
0x0000564afe32d969 <+24>: mov (%rax),%eax
0x0000564afe32d96b <+26>: lea 0x1(%rax),%edx
0x0000564afe32d96e <+29>: mov -0x8(%rbp),%rax
0x0000564afe32d972 <+33>: mov %edx,(%rax)
0x0000564afe32d974 <+35>: lea 0x73e(%rip),%rdi

不难发现,在 <+12> 时,把 rbp-0x8 的值设置为 0,随后把 rbp-0x8 的值(0) 赋值给了 rax 寄存器,而后在对于 rax 寄存器的值作为地址的解析都将触发 segment fault ,所以应当避开这些指令。

Building a WebServer