Skip to main content

11月小结

·214 words·2 mins
Table of Contents

华子杯 线下pwn4 #

华子杯2024线下,啊太久没做pwn了,修了两个签到,记个工具脚本的使用

格式化字符串漏洞例子 - CTF Wiki

fix:fix了半天printf的fmt字符,结果puts也能过check

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
  sub_86A(a1, a2, a3);
  while ( 1 )
  {
    puts(">> ");
    read(0, format, 0x10uLL);
    if ( !strncmp(format, "exit", 4uLL) )
      break;
    printf(format);
  }
  exit(0);
}
.text:0000000000000926 ; ---------------------------------------------------------------------------
.text:0000000000000926
.text:0000000000000926 loc_926:                                ; CODE XREF: main+4F↑j
.text:0000000000000926                 lea     rdi, format     ; format
.text:000000000000092D                 mov     eax, 0
.text:0000000000000932                 call    _printf
.text:0000000000000937                 jmp     short loc_8D9
.text:0000000000000937 ; } // starts at 8CB
.text:0000000000000937 main            endp
.text:0000000000000937
.text:0000000000000937 ; ---------------------------------------------------------------------------

嗷嗷,这个脚本好用,一个快速帮你找可用的段并把机器码快速写到对应地方的工具

aftern00n/AwdPwnPatcher

但是由于format是写在bss段上的,所以无法用栈上的偏移来写,所以要用qword ptr [0x201050]来定位format的位置

.bss:0000000000201050 ; char format[16]
.bss:0000000000201050 format          db 10h dup(?)           ; DATA XREF: main+1Fo
.bss:0000000000201050                                         ; main+41o ...
.bss:0000000000201050 _bss            ends
.bss:0000000000201050

x64_patcher.py

from AwdPwnPatcher import *
binary = "./pwn"
awd_pwn_patcher = AwdPwnPatcher(binary)
fmt_offset = awd_pwn_patcher.add_constant_in_ehframe("%s\x00\x00")
# 传参顺序 rdi, rsi, rdx, rcx
assembly = """
lea rsi, qword ptr [0x201050]
lea rdi, qword ptr [{}]
""".format(hex(fmt_offset))
awd_pwn_patcher.patch_by_jmp(0x926, jmp_to=0x932, assembly=assembly)
awd_pwn_patcher.save()

效果

.eh_frame:0000000000000A18 ; ===========================================================================
.eh_frame:0000000000000A18
.eh_frame:0000000000000A18 ; Segment type: Pure data
.eh_frame:0000000000000A18 ; Segment permissions: Read
.eh_frame:0000000000000A18 _eh_frame       segment qword public 'CONST' use64
.eh_frame:0000000000000A18                 assume cs:_eh_frame
.eh_frame:0000000000000A18                 ;org 0A18h
.eh_frame:0000000000000A18 aS              db '%s',0               ; DATA XREF: .eh_frame:0000000000000A23o
.eh_frame:0000000000000A1B                 db    0
.eh_frame:0000000000000A1C ; ---------------------------------------------------------------------------
.eh_frame:0000000000000A1C                 lea     rsi, s1         ; CODE XREF: main:loc_926j
.eh_frame:0000000000000A23                 lea     rdi, aS         ; "%s"
.eh_frame:0000000000000A2A                 jmp     loc_932
.eh_frame:0000000000000A2A ; ---------------------------------------------------------------------------

有时puts的换行会过不了check(虽然现在也很少有闲心去查这种东西了)

估计再过几年这种技巧就会变成旧时代的余党吧