我寫了這個簡單的 c 程式來解釋具有相同特徵的更困難的問題。
#include <stdio.h> int main(int argc, char *argv[]) { int n; while (1){ scanf("%d", &n); printf("%d\n", n); } return 0; }
它按預期工作。
我還編寫了一個子進程腳本來與該程式互動:
from subprocess import popen, pipe, stdout process = popen("./a.out", stdin=pipe, stdout=pipe, stderr=stdout) # sending a byte process.stdin.write(b'3') process.stdin.flush() # reading the echo of the number print(process.stdout.readline()) process.stdin.close()
問題是,如果我執行 python 腳本,執行會在 readline()
上凍結。事實上,如果我中斷腳本,我會得到:
/tmp » python script.py ^ctraceback (most recent call last): file "/tmp/script.py", line 10, in <module> print(process.stdout.readline()) ^^^^^^^^^^^^^^^^^^^^^^^^^ keyboardinterrupt
如果我更改我的 python 腳本:
from subprocess import popen, pipe, stdout process = popen("./a.out", stdin=pipe, stdout=pipe, stderr=stdout) with process.stdin as pipe: pipe.write(b"3") pipe.flush() # reading the echo of the number print(process.stdout.readline()) # sending another num: pipe.write(b"4") pipe.flush() process.stdin.close()
我得到了這個輸出:
» python script.py b'3\n' Traceback (most recent call last): File "/tmp/script.py", line 13, in <module> pipe.write(b"4") ValueError: write to closed file
這意味著第一個輸入已正確發送,並且讀取已完成。
我真的找不到解釋這種行為的東西;有人可以幫助我理解嗎? 提前致謝
[編輯]:由於有很多要點需要澄清,所以我添加了此編輯。我正在使用 rop
技術進行緩衝區溢出漏洞利用的培訓,並且我正在編寫 python 腳本來實現這一目標。為了利用這個漏洞,由於aslr,我需要發現libc
位址並使程式重新啟動而不終止。由於腳本將在目標機器上執行,我不知道哪些庫可用,那麼我將使用 subprocess,因為它是內建於 python 中的。不詳細說明,攻擊在第一個scanf
上發送一系列位元組,目的是洩漏libc
基底位址並重新啟動程式;然後發送第二個有效負載以獲得一個shell,我將透過它以互動模式進行通訊。
這就是為什麼:
- 我只能使用內建函式庫
- 我必須傳送位元組並且無法附加結尾
\n
:我的有效負載將無法對齊或可能導致失敗 - 我需要保持
stdin
打開 - 我無法更改 c 程式碼
正確答案
更改這些:
-
在 c 程式讀取的數字之間發送分隔符號。 scanf(3) 接受任何非數字位元組作為分隔符號。為了最簡單的緩衝,請從 python 發送換行符(例如
.write(b'42\n')
)。如果沒有分隔符,scanf(3) 將無限期地等待更多數字。 -
每次寫入(c 和 python 中)後,刷新輸出。
這對我有用:
#include <stdio.h> int main(int argc, char *argv[]) { int n; while (1){ scanf("%d", &n); printf("%d\n", n); fflush(stdout); /* i've added this line only. */ } return 0; }
import subprocess p = subprocess.popen( ('./a.out',), stdin=subprocess.pipe, stdout=subprocess.pipe) try: print('a'); p.stdin.write(b'42 '); p.stdin.flush() print('b'); print(repr(p.stdout.readline())); print('c'); p.stdin.write(b'43\n'); p.stdin.flush() print('d'); print(repr(p.stdout.readline())); finally: print('e'); print(p.kill())
原始 c 程式在終端機視窗中交互運行時能夠正常工作的原因是,在 c 中,當將換行符 (\n
) 寫入終端時,輸出會自動刷新。因此 printf("%d\n", n);
最後會隱含執行 fflush(stdout);
。
當使用 subprocess
從 python 運行時,原始 c 程式無法工作的原因是它將輸出寫入管道(而不是終端),並且沒有自動刷新到管道。發生的情況是,python 程式正在等待字節,而c 程式不會將這些位元組寫入管道,但它正在等待更多位元組(在下一個scanf
中),因此兩個程式都在無限期地等待對方。 (但是,在輸出幾 kib(通常為 8192 位元組)後,將會出現部分自動刷新。但是單個十進制數太短,無法觸發該操作。)
如果無法更改 c 程序,那麼您應該使用終端設備而不是管道來在 c 和 python 程式之間進行通訊。 pty
python 模組可以建立終端設備,這對我來說適用於你的原始 c 程式:
import os, pty, subprocess master_fd, slave_fd = pty.openpty() p = subprocess.popen( ('./a.out',), stdin=slave_fd, stdout=slave_fd, preexec_fn=lambda: os.close(master_fd)) try: os.close(slave_fd) master = os.fdopen(master_fd, 'rb+', buffering=0) print('a'); master.write(b'42\n'); master.flush() print('b'); print(repr(master.readline())); print('c'); master.write(b'43\n'); master.flush() print('d'); print(repr(master.readline())); finally: print('e'); print(p.kill())
如果你不想從python發送換行符,這裡有一個沒有換行符的解決方案,它對我有用:
import os, pty, subprocess, termios master_fd, slave_fd = pty.openpty() ts = termios.tcgetattr(master_fd) ts[3] &= ~(termios.ICANON | termios.ECHO) termios.tcsetattr(master_fd, termios.TCSANOW, ts) p = subprocess.Popen( ('./a.out',), stdin=slave_fd, stdout=slave_fd, preexec_fn=lambda: os.close(master_fd)) try: os.close(slave_fd) master = os.fdopen(master_fd, 'rb+', buffering=0) print('A'); master.write(b'42 '); master.flush() print('B'); print(repr(master.readline())); print('C'); master.write(b'43\t'); master.flush() print('D'); print(repr(master.readline())); finally: print('E'); print(p.kill())
以上是C程式和子進程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Python3.6環境下加載Pickle文件報錯:ModuleNotFoundError:Nomodulenamed...

如何解決jieba分詞在景區評論分析中的問題?當我們在進行景區評論分析時,往往會使用jieba分詞工具來處理文�...

如何使用正則表達式匹配到第一個閉合標籤就停止?在處理HTML或其他標記語言時,常常需要使用正則表達式來�...

攻克Investing.com的反爬蟲策略許多人嘗試爬取Investing.com(https://cn.investing.com/news/latest-news)的新聞數據時,常常�...


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版
中文版,非常好用

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。