Skip to content

Commit

Permalink
chapters/memory-security: Add content for buffer management and overf…
Browse files Browse the repository at this point in the history
…lows

Add Reading and Tasks and modify config.yaml to render the laboratory

Signed-off-by: NickZaharia308 <[email protected]>
  • Loading branch information
NickZaharia308 authored and teodutu committed Jun 24, 2024
1 parent d7e7cf8 commit 3dfe9fd
Show file tree
Hide file tree
Showing 49 changed files with 1,469 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Buffer in the `.data` Section

Navigate to the `drills/tasks/data-buffer/support/` directory in the laboratory's resource archive and open the `data_buffer.asm` file.
This file contains a program that populates a buffer with information and then displays it.

Carefully review the program, then compile it using the command:

```bash
make
```

Notice that after running the above compilation command, both an object file and an executable file are generated. You can verify this by running the command:

```Bash
ls
```

Run the program using the executable file, using the command:

```Bash
./data_buffer
```

Observe the behavior of the program based on its code.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data_buffer
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
AS = nasm
CC = gcc
RM = rm

SRCS := $(shell find . -name "*.asm")
OBJS := $(SRCS:.asm=.o)

ASFLAGS ?= -f elf32 -F dwarf
CFLAGS ?= -Wall
LDFLAGS ?= -m32 -no-pie

TARGET_EXEC = data_buffer

$(TARGET_EXEC): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

$(OBJS): $(SRCS)
$(AS) $(ASFLAGS) $< -o $@

.PHONY: clean

clean:
$(RM) -r *.o $(TARGET_EXEC)
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
; SPDX-License-Identifier: BSD-3-Clause


; Fill buffer with data and print it.
; Buffer is stored in .data section (initialized data).

extern printf
extern puts

section .data
buffer: times 64 db 5
len: equ $-buffer

buffer_intro_message: db "buffer is:", 0
byte_format: db " %02X", 0
null_string: db 0

section .text

global main

main:
push ebp
mov ebp, esp

; Fill data in buffer: buffer[i] = i + 1
; ecx is buffer index (i), dl is buffer value (i + 1). dl needs to be ecx + 1.
; Buffer length is 64 bytes.
xor ecx, ecx
fill_byte:
mov dl, cl
inc dl
mov byte [buffer + ecx], dl
inc ecx
cmp ecx, len
jl fill_byte

; Text before printing buffer.
push buffer_intro_message
call printf
add esp, 4

xor ecx, ecx
print_byte:
xor eax, eax
mov al, byte[buffer + ecx]
push ecx ; save ecx, printf may change it

; Print current byte.
push eax
push byte_format
call printf
add esp, 8

pop ecx ; restore ecx
inc ecx
cmp ecx, len
jl print_byte

; Print new line. C equivalent instruction is puts("").
push null_string
call puts
add esp, 4

leave
ret
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Buffer Overflow with Data from Standard Input and `fgets()`

As mentioned in the [**Read Using gets** task](../read-stdin-gets/README.md), the `gets()` function is prohibited in current programs.
Instead, the `fgets()` function can be used.
Open the source code file `read_stdin_fgets.asm` from the `drills/tasks/read-stdin-fgets/support/`.
In the `read_stdin_fgets.asm` source file, follow **TODO 1** and change the `gets()` function call to the `fgets()` function call.

For the `fgets()` call, read from standard input.
As an argument for the third parameter of `fgets()` (of type `FILE *`) you will use standard input.
To specify standard input, use the `stdin` stream.
You will need to mark it as external using, at the beginning of the assembly language file, the construction:

> ```Assembly
> extern stdin
> ```
`stdin` is an address; to call `fgets()` with standard input,
it is sufficient to pass on the stack the value from the `stdin` address, i.e., using the construction:

```Assembly
push dword [stdin]
```

> **HINT** Follow the manual page of the [`fgets()`](https://man7.org/linux/man-pages/man3/fgets.3.html) function to find out what parameters it receives.
> **TIP** Since the `fgets()` function has 3 parameters (which occupy `3 × 4 = 12` bytes) you will need to use `add esp, 12` after the function call,
> in restoring the stack, instead of `add esp, 4` as in the case of the program above that used `gets()`.
> **IMPORTANT** Do not modify the assembly language code. Transmit the input string in the appropriate format to the standard input
> to generate a buffer overflow and to obtain the required result.
Follow **TODO 2** in code and call *fgets()* instead of gets, but keep in mind that you will have to push a value big enough for the buffer size in order to produce an overflow.
The result should be the same like in the *read_stdin_gets* task.

> **TIP** As above, to transmit the input string for the program, it is recommended to write it in a file
> and then redirect that file to the corresponding program command.
> Redirecting the `payload` file to the program is done using a command like:
```Bash
./read_stdin_fgets < payload
```

What happens if you push *buffer_length - 1*, instead of *buffer_length*.
Why *var is 0x004F4C46* now?

If you're having difficulties solving this exercise, go through [this](../../../reading/README.md#How-to-make-a-Buffer-Overflow?) reading material.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
read_stdin_fgets
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFLOW
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
; SPDX-License-Identifier: BSD-3-Clause


; Fill buffer with data from standard input.
; Buffer is stored on the stack.

extern printf
extern puts
extern strlen
extern fgets
extern stdin

section .data
read_message: db "insert buffer string: ", 0
buffer_intro_message: db "buffer is:", 0
byte_format: db " %02X(%c)", 0
null_string: db 0
var_message_and_format: db "var is 0x%08X", 13, 10, 0

section .text

global main

main:
push ebp
mov ebp, esp

; Make room for local variable (32 bit, 4 bytes).
; Variable address is at ebp - 4.
sub esp, 4

; Make room for buffer (64 bytes).
; Buffer address is at ebp - 68.
sub esp, 64

; Initialize local variable.
mov dword [ebp - 4], 0xCAFEBABE

; Read buffer from standard input.
push read_message
call printf
add esp, 4

; The buffer has only 64 bytes of memmory allocated
; The last one is for null terminator
; So, with 64 + 1 + 4 = 69
; There can still be a full overflow of local var
; I suggest observing the code with 68 instead
; as well.
lea ebx, [ebp-68]
push dword [stdin]
push 69
push ebx
call fgets
add esp, 12

; Push string length on the stack.
; String length is stored at ebp - 72.
push ebx
call strlen
add esp, 4
push eax

; Text before printing buffer.
push buffer_intro_message
call printf
add esp, 4

xor ecx, ecx
print_byte:
xor eax, eax
lea ebx, [ebp - 68]
mov al, byte[ebx + ecx]
push ecx ; save ecx

; Print current byte.
push eax
push eax
push byte_format
call printf
add esp, 12

pop ecx ; restore ecx
inc ecx
cmp ecx, [ebp - 72]
jl print_byte

push null_string
call puts
add esp, 4

; Print local variable.
mov eax, [ebp - 4]
push eax
push var_message_and_format
call printf
add esp, 8

leave
ret
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
read_stdin_fgets
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
AS = nasm
CC = gcc
RM = rm

SRCS := $(shell find . -name "*.asm")
OBJS := $(SRCS:.asm=.o)

ASFLAGS ?= -f elf32 -F dwarf
CFLAGS ?= -Wall
LDFLAGS ?= -m32 -no-pie

TARGET_EXEC = read_stdin_fgets

$(TARGET_EXEC): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

$(OBJS): $(SRCS)
$(AS) $(ASFLAGS) $< -o $@

.PHONY: clean

clean:
$(RM) -r *.o $(TARGET_EXEC)
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
; SPDX-License-Identifier: BSD-3-Clause


; Fill buffer with data from standard input.
; Buffer is stored on the stack.

; TODO 1: Add missing external declaration for stdin
; TODO 1: Change gets to fgets function.
extern printf
extern puts
extern strlen
extern gets


section .data
read_message: db "insert buffer string: ", 0
buffer_intro_message: db "buffer is:", 0
byte_format: db " %02X(%c)", 0
null_string: db 0
var_message_and_format: db "var is 0x%08X", 13, 10, 0

section .text

global main

main:
push ebp
mov ebp, esp

; Make room for local variable (32 bit, 4 bytes).
; Variable address is at ebp - 4.
sub esp, 4

; Make room for buffer (64 bytes).
; Buffer address is at ebp - 68.
sub esp, 64

; Initialize local variable.
mov dword [ebp - 4], 0xCAFEBABE

; Read buffer from standard input.
push read_message
call printf
add esp, 4

lea ebx, [ebp - 68]

; TODO 2: Call fgets function instead of gets.
; HINT: fgets takes 3 arguments: buffer address, buffer size, and stdin.
; IMPORTANT: remember the order of arguments that have to be pushed.
push ebx
call gets
add esp, 4

; Push string length on the stack.
; String length is stored at ebp - 72.
push ebx
call strlen
add esp, 4
push eax

; Text before printing buffer.
push buffer_intro_message
call printf
add esp, 4

xor ecx, ecx
print_byte:
xor eax, eax
lea ebx, [ebp - 68]
mov al, byte[ebx + ecx]
push ecx ; save ecx, printf may modify it

; Print current byte.
push eax
push eax
push byte_format
call printf
add esp, 12

pop ecx ; restore ecx
inc ecx
cmp ecx, [ebp - 72]
jl print_byte

push null_string
call puts
add esp, 4

; Print local variable.
mov eax, [ebp - 4]
push eax
push var_message_and_format
call printf
add esp, 8

leave
ret
Loading

0 comments on commit 3dfe9fd

Please sign in to comment.