S2e-env环境及编译学习1
Ⅰ、S2e符號執行概述
Ⅱ、前言
對于S2E做符號執行,當前只是了解一些表面的功能,因此本文只是大致記錄本人對于s2e和符號執行的一點粗淺認識僅供初學者參考。如果謬誤之處,還希望大家指正,謝謝。
一、S2E和符號執行
首先簡單描述一下什么是符號執行。我們平常執行程序的時候,使用的都是具體值來執行程序,得到輸出。這種執行方式稱為實際(具體)執行(concolic execution)。在使用不同的具體值執行程序時,程序可能走不同的路徑,執行的行為就可能存在差異。那么怎么才能知道程序可能存在哪些執行路徑,進而去了解程序各種各樣的執行行為呢?
符號執行的核心思想就是使用符號值來代替具體值來執行待測程序。舉個例子:程序某函數(方法)如:func(int x, int y)接受兩個輸入x和y,并輸出兩者中較大的那個值。
在進行符號執行時,將x和y分別賦予符號值X和Y,之后執行程序,并記錄符號執行狀態(包括:路徑條件,符號狀態和程序計數器)。碰到分支時,執行路徑一分為二,分別代表滿足條件和不滿足條件時的執行路徑。符號執行的所有狀態構成符號執行樹,表示程序的所有執行路徑。在符號執行樹中,節點表示狀態,箭頭表示狀態的遷移。(如下圖所示)
在符號執行過程中,程序的路徑會隨著程序規模的增大而急速擴大(即“路徑爆炸問題”),這個問題會制約符號執行的性能,為了解決這個問題,V.Chipounov等人提出了選擇符號執行(Selective Symbolic Execution)技術,只對用戶關系的代碼符號化執行,對其余代碼則使用實際執行。
S2E是一個選擇符號執行工具(平臺),在Klee、Qemu的基礎上構建而來。Klee用來進行符號執行,Qemu虛擬機作為符號執行的載體。根據S2E官方文檔得知,目前S2E提供兩種安裝方案:
1、使用s2e-env.(s2e-env是一個基于 Python 的工具)
不使用s2e-env,通過Docker來構建。(詳細可參考官方文檔,建議是使用第一種,相對簡單一些)。(官方文檔:http://s2e.systems/docs/BuildingS2E.html)
下面分析基本的安裝過程及我所遇到過的問題。
(注:安裝該環境最好使用ubuntu20.04及以上版本,18.04以下版本可能后續已不支持)
Ⅲ、S2e-env搭建和代碼分析
一、安裝s2e-env
1、可以使用以下命令從GitHub獲取和build
(a)、安裝git, python3和pip等工具
(b)、拉取s2e-env代碼到本地
git clone https://github.com/s2e/s2e-env.gitcd s2e-env (c)、配置環境 python3 -m venv venv . venv/bin/activate install --upgrade pip//By default, s2e-env uses https to clone repositories.
//If you want ssh, please edit s2e_env/dat/config.yaml before running pip install.
//If your key is password-protected, use ssh-agent.
(d)、切換到s2e-env的目錄執行,執行如下命令
// Note: if your pip version is earlier than v19, use the following command:pip install --process-dependency-links .
3、述執行沒有問題下,可以試試s2e的命令是否有效,有效則說明成功。(如下圖)
二、s2e init流程(創建新環境)
(一)、s2e init流程:
1、S2E環境有S2E引擎和相關工具、一個或多個虛擬機映像和一個或多個分析目標(稱為“項目”)組成。
要在中創建新的S2E環境如/home/usr/s2e, 請運行:
S2e init /home/usr/s2e
這步的作用主要是在DIR目錄下初始化一個s2e的環境,包括安裝一些依賴的工具以及從github上拉取各種代碼和子模塊,該步由于國內網絡問題,容易出現的是repo init失敗。(具體問題下文問題總結)
完成時候需要配置環境如:source /home/usr/s2e/new-s2e/s2e_activate(成功后有提示,路徑是由創建者決定并不都是一樣)
這一步正確完成會有如下提示:
三、s2e init流程代碼分析
(一)、s2e init流程代碼分析:
1、file: s2e_env/manage.py
入口函數:main{(1)、configure_logging配置全局log,(2)、創建CommandManager對象并調用execute, execute解析命令,設置argv參數。}
解析subcommand(如s2e -help、 s2e init等),
實際參與執行的流程:main —> manager.execute()
2、file: s2e_env/command.py
調用fetch_command和run_from_argv,此時以進入s2e_env/command.py, fetch_command會獲取s2e_env/commands目錄下所有模塊對應的命令
通過run_from_argv調用execute—>handle, 進入s2e_env/commands/init.py}
其中fetch_command()函數中通過load_command_class方法來完成venv虛擬環境的準備工作。后續s2e build和s2e build_image在執行腳本是子類方法調用都會進入venv中的腳本(路徑如:s2e-env/venv/lib/python3.8/site-packages/s2e_env/commands/build.py)
3、file: s2e_env/commands/init.py
(1)、class Command(BaseCommand) -->handle(改函數會通過命令行獲取需要檢查創建的new環境目錄,如:s2e init /home/usr/new-s2e,
此時該函數拿到需要創建的目錄就是/home/usr/new-s2e)。代碼:if not os.path.isdir(env_path)
(2)、創建該目錄后,依次在該目錄中創建s2e環境需要的各種工作目錄:如:build、images、install、source等。主要執行位置:for dir_ in CONSTANTS[‘dirs’]:
(3)、_create_config()函數創建s2e.yaml文件
(4)、_create_activate_script()函數創建s2e_activate.sh文件(該文件后續需要在shell命令行下執行,主要是部署環境變量,便于在任意目錄使用s2e命令)
(5)、_install_dependencies()函數僅依靠apt-get開始Install S2E’s dependencies,如果這一步失敗,則會進入異常處理刪除已經創建的工作目錄。
代碼:if os.path.isdir(env_path) and os.getcwd() != env_path:
注:主要是利用apt-get來下載安裝
(6)、_get_s2e_sources()函數從https://gerrit.googlesource.com/git-repo下載repo工具,通過repo開始往source中拉取s2e_env的主要代碼
代碼:logger.info(‘Fetching %s from %s’, git_s2e_repo, git_url)
repo.init(u=f’{git_url}/{git_s2e_repo}’, b=manifest_branch,
_out=sys.stdout, _err=sys.stderr)
repo.sync(_out=sys.stdout, _err=sys.stderr)
成功之后有如下提示:
四、、s2e build流程:
(一)、s2e build流程:
1、構建S2E,執行后下命令
s2e builds2e build 將構建所有 S2E 組件,包括 KLEE、QEMU、libs2e、Z3等。這個過程耗時比較久,大約1小時左右,成功則如下圖所示
注:s2e build耗時比較長,這個過程需要保證網絡的通暢以及一定的速度,不然容易失敗。
3、接下來,需要構建一個虛擬機鏡像供分析目標使用。構建image(虛擬機)s2e提供的虛擬機有很多種,這次我選擇的是“debian-9.2.1-x86_64”(成功如下圖所示)
s2e image_build debian-9.2.1-x86_64
注:鏡像構建過程會緩存中間構建輸出,.tmp-output該輸出可能會變得非常大。構建映像后,如果磁盤空間存在問題,您可能希望刪除此目錄。
五、s2e build流程代碼分析
(一)、s2e build流程代碼分析:
1、file: s2e_env/manage.py
入口執行流程:main —> manager.execute()
— 前面已有圖解說明,此處不在贅述。—
2、file: s2e_env/command.py
調用fetch_command和run_from_argv,此時已經進入s2e_env/command.py, fetch_command會獲取s2e_env/commands目錄下所有模塊對應的命令
通過run_from_argv調用execute—>handle,
進入s2e-env/venv/lib/python3.8/site-packages/s2e_env/commands/build.py。之前venv部署的虛擬環境},如下代碼所示:
至此由Python腳本轉入Makfile開始進入編譯流程。
3、s2e/build-test2/source/scripts/Makefile
如圖所示,這個Makefile屬于頂層控制,并未做具體的事情。具體的工作主要有include引入的兩個Makefile來完成,可以簡單認為是2個階段的編譯。其中第一階段會有一些依賴的下載,需要保持良好的網絡(會訪問國外站點)
4、s2e/build-test2/source/s2e/Makefile
注:執行該Makefile需要依賴cmake工具,在安裝步驟中請注意環境中是否已經準備。
該Makefile主要完成一下工作:
(a)、檢查環境中build目錄是否已經ready并設置S2E環境相關各種變量(如arch, LLVM等)。
(b)、設置guest_tools的下載地址
(c)、set各類依賴工具下載地址
(d)、主體編譯任務如下
(e)、設置KLEE和LLVM編譯內容
(f)、設置開始之前各種依賴工具的下載(大致如下),如果網絡有問題,不妨參考修改本Makefile,使用其他下載方式,下載好后copy在Makefile指定位置即可。
(g)、編譯各類依賴工具(如下圖舉例說明)
(h)、編譯libs2e庫
(i)、部署Guest tools工具并安裝
(j)、第二階段qemu的編譯
s2e/build-test2/source/scripts/Makefile.qemu,這個Makefike相對內容比較少,僅僅只是針對qemu的編譯(s2e執行時,會依賴qemu的環境),內容大致如下圖所示:
六、s2e image_build流程代碼分析
(一)、s2e image_build流程:
如命令:`s2e image_build debian-9.2.1-x86_64`其中debian-9.2.1-x86_64是之前s2e build過程中已經在新的環境目錄new_dir/images中已經下載好的。
(二)、s2e image_build流程代碼分析:
1、file: s2e_env/manage.py
入口執行流程:main —> manager.execute()
前面已有圖解說明,此處不在贅述。
2、file: s2e_env/command.py
調用fetch_command和run_from_argv,此時已進入s2e_env/command.py, fetch_command會獲取s2e_env/commands目錄下所有模塊對應的命令
通過run_from_argv調用execute—>handle,
進入s2e-env/venv/lib/python3.8/site-packages/s2e_env/commands/image_build.py。
image_build.py大致如下代碼所示:
Ⅳ、構建一個新的分析項目
一、創建新項目
完成上面步驟后,現在已經有了一個可用于分析程序的虛擬機映像(virtual machine image)。接下來需要創建一個“項目”來分析咱們的目標程序,而要創建這樣的一個項目,需運行如下命令:
s2e new_project --image <image_name> /path/to/target/binary [target_args...]首先來看命令的參數解析:
用一個例子來說說明,有一個可執行程序sample,路徑是/home/usrname/xxx/sample, 虛擬機路徑是/home/usrname/s2e/new-s2e/images/debian-9.2.1-x86_64, 那么創建一個符號執行工程的命令是如下:
執行后有打印提示如下
二、開始執行
執行完cd /home/usr/s2e/new-s2e/projects/sample && ./launch-s2e.sh后,運行命令:s2e run sample會有如下圖所示提示:
三、查看執行結果
在/home/usrname/s2e/new-s2e/projects/sample中有個名稱中包含著out的文件夾存放著符號執行的結果,文件夾內容大致如下圖所示:
Ⅴ、構建一個新的分析項目
一、s2e newproject執行環境
1、file: s2e-env/s2e_env/manage.py
main -----> manage.execute() ----> execute(“Identify” subcommand) ---->self.fetch_command(subcommand).run_from_argv(self._argv)fetch_command(subcommand) ---->load_command_class(subcommand) ----> importlib.import_module(f's2e_env.commands.{name}')2、file: /usr/lib/python3.8importlib/init.py
importlib.import_module ----> import_module --→_bootstrap._gcd_import3、file: s2e-env/s2e_env/commands/new_project.py
from s2e_env.command import EnvCommand, CommandErrorfrom s2e_env.commands.project_creation import CGCProject, LinuxProject, AbstractProject........4、file: s2e-env/s2e_env/commands/project_creation/init.py
from .abstract_project import AbstractProject........5、file: s2e-env/s2e_env/commands/project_creation/cgc_project.py
from s2e_env.command import CommandError........6、file: s2e-env/s2e_env/commands/project_creation/base_project.py
from s2e_env.command import CommandErrorfrom s2e_env.commands.recipe import Command as RecipeCommandfrom s2e_env.manage import call_command........7、file: s2e-env/s2e_env/venv/lib/python3.8/site-packages/pwn/toplevel.py
import pwnlib........8、file: s2e-env/s2e_env/venv/lib/python3.8/site-packages/pwnlib/init.py
for module in __all__:importlib.import_module('.%s' % module, 'pwnlib')--------------------------- __all__ = ['args','asm','atexception','atexit','commandline','constants','context','data','dynelf','encoders','elf','exception','fmtstr','gdb','libcdb','log','memleak','pep237','regsort','replacements','rop','runner','shellcraft','term','tubes','ui','useragents','util','adb','update', ]9、file: s2e-env/s2e_env/venv/lib/python3.8/site-packages/pwnlib/term/unix_termcap.py
if cache is None:init() s = cache.get(cap) if not s:s = curses.tigetstr(cap)if s is None:s = curses.tigetnum(cap)if s == -2:s = curses.tigetflag(cap)if s == -1:# default to empty string so tparm doesn't fails = ''else:s = bool(s)cache[cap] = s # if `s' is not set `curses.tparm' will throw an error if given arguments if args and s:return curses.tparm(s, *args) else:return s10、file: s2e-env/s2e_env/venv/lib/python3.8/site-packages/pwnlib/term/text.py
class Module(types.ModuleType):def __init__(self):self.__file__ = __file__self.__name__ = __name__self.num_colors = 8self.has_bright = self.num_colors >= 16self.has_gray = self.has_brightself.when = 'auto'self._colors = {'black': 0,'red': 1,'green': 2,'yellow': 3,'blue': 4,'magenta': 5,'cyan': 6,'white': 7,}self._reset = termcap.get('reset')self._attributes = {}for x, y in [('italic' , 'sitm'),('bold' , 'bold'),('underline', 'smul'),('reverse' , 'rev')]:s = termcap.get(y)if not hasattr(s, 'encode'):s = s.decode('utf-8')self._attributes[x] = sself._cache = {}.......11、file: s2e-env/s2e_env/venv/lib/python3.8/site-packages/pwn/init.py
pwnlib.args.initialize()12、file: s2e-env/s2e_env/commands/recipe.py
from s2e_env.command import ProjectCommand......13、file:s2e-env/s2e_env/commands/project_creation/base_project.py
class BaseProject(AbstractProject):......14、file:s2e-env/s2e_env/commands/project_creation/cgc_project.py
class CGCProject(BaseProject):......15、file:s2e-env/s2e_env/commands/project_creation/linux_project.py
from s2e_env.analysis.elf import ELFAnalysis......16、file:s2e-env/s2e_env/analysis/elf.py
from elftools.elf.dynamic import DynamicSegment from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSectionfrom s2e_env import CONSTANTSclass ELFAnalysis:"""Support class for doing some simple static analysis on ELF files."""def __init__(self, elf_path):self._elf_path = elf_pathself._elf_file = Noneself._elf = Nonedef __enter__(self):self._elf_file = open(self._elf_path, 'rb')self._elf = ELFFile(self._elf_file)return self.......二、s2e newproject執行流程
1、file: s2e_env/manage.py
入口函數:main{(1)、configure_logging配置全局log,(2)、創建CommandManager對象并調用execute, execute解析命令,設置argv參數。
解析subcommand(如s2e -help、 s2e init等),
2、file: s2e_env/command.py
調用fetch_command和run_from_argv,此時進入s2e_env/command.py, fetch_command會獲取s2e_env/commands目錄下所有模塊對應的命令
通過run_from_argv調用execute—>handle, 進入s2e_env/commands/init.py}
3、file: s2e_env/manage.py self.fetch_command(subcommand).run_from_argv(self._argv) —> run_from_argv(self._argv)
4、file: s2e_env/command.py BaseCommand::execute(153, 175)–>handle
5、file: s2e_env/commands/new_project.py 該模塊的handle函數被調用,
6、file: s2e_env/commands/linux_project.py //(class LinuxProject(BaseProject),這里通過基類構造函數調入基類)
class LinuxProject(BaseProject):supported_tools = ['pov']def __init__(self):super().__init__('bootstrap.linux.sh', 's2e-config.linux.lua')def _is_valid_image(self, target, os_desc):return is_valid_arch(target.arch, os_desc) and 'elf' in os_desc['binary_formats']def _analyze_target(self, target, config):with ELFAnalysis(target.path) as elf:config['dynamically_linked'] = elf.is_dynamically_linked()config['modelled_functions'] = elf.get_modelled_functions()def _finalize_config(self, config):config['project_type'] = 'linux'7、file:s2e_env/commands/project_creation/base_project.py
a、第6步通過基類拷貝構造函數,調用到此處
b、這里父類(class BaseProject)的構造函數拿到2個shell的字符串參數,然后返回class LinuxProject(BaseProject),繼續執行。
c、重新返回第5步調用,call_command,這里調用回到file: s2e_env/manage.py的call_command重新調用ommand.execute(這里應該有一個調用堆棧)
d、調用至file: s2e_env/command.py BaseCommand::execute(153, 175)–>handle
e、此時調用進入file:s2e_env/commands/project_creation/AbstractProject_project.py(class BaseProject(AbstractProject)的基類)。self._create()函數
8、file:s2e_env/commands/project_creation/AbstractProject_project.py
a、第7步調用進入子類函數:def _create_bootstrap(self, project_dir, config)
b、在子類進行一些列創建,后返回
9、file:file:s2e_env/commands/project_creation/AbstractProject_project.py
a、子類完成創建動作后返回。
Ⅵ、s2e_env搭建問題總結
問題1:執行pip install .安裝部分依賴軟件時有可能出現訪問站點失敗的問題。
問題原因:
2、需要給虛擬機命令行配置代理,確保其可以正常訪問外部站點。
解決方法:
1、 終端運行如下命令:
export http_proxy=’IP : 端口’
export https_proxy=’IP : 端口’
2、如果上述方式不能解決,則需配置pip工具的proxy或者直接執行如下命令
pip3 --proxy http://IP : 端口 install .(如:pip3 --proxy http://192.168.0.X:108X install .)
3、給wget配置代理:
(a)、 cd ~
(b)、 vim .wgetrc
?、增加如下命令
proxy_user = user
proxy_password = password
use_proxy = on
問題2、執行命令后,許多站點可以ping通,但是無法訪問
問題解決:
(1)、備份apt的source.list文件(sudo cp /etc/apt/sources.list /etc/apt/sources.list.bk)
(2)、替換apt的源,如用阿里的源(https://www.cnblogs.com/zqifa/p/12910989.html)
問題3、ssh執行報錯
問題原因:
缺失ssh相關組件和依賴
問題解決:
執行如下命令解決:
sudo apt-get autoremove openssh-client
sudo apt-get install openssh-client openssh-sftp-server openssh-server ssh
sudo apt-get install ssh-askpass
問題4、ssh拉取代碼報權限錯誤
問題原因:
本地git賬戶信息配合,并與github郵箱關聯
問題解決:
參考文檔:https://blog.csdn.net/qq_34942306/article/details/104585821
過程說明:成功之后會有如下提示,許執行source及build
問題5:repo 拉取代碼失敗
問題原因:repo工具沒有安裝成功,且有可能repo找不到python
問題解決:
sudo apt-get install repo
問題6:build時有可能出現tar解壓失敗問題
問題原因:
1、可能是拉取的代碼源文件所損壞(查看源文件大小)
2、配置~/.wgetrc文件
http_proxy = http://your_proxy:port
https_proxy = http://your_proxy:port
問題解決:
刪除生成文件中的build目錄。重新執行一遍builds2e init xxx。
問題7:KVM interface not found
問題解決:
出現這個問題如果使用的是虛擬機說明虛擬機沒有開CPU虛擬化(設置后重啟)。如果是真機,那么可能是CPU不支持虛擬化。
問題8:如果github部分站點無法訪問,代理配置又查不到問題
問題解決:
直接對/etc/hosts文件進行配置
1、使用命令sudo vim /etc/hosts增加報錯的站點ip(如下圖所示)
問題9:git拉取報錯:GnuTLS recv error(-54): Error in the full function
問題原因:可能是網速緩慢,中斷,git緩存不夠導致
問題解決:直接對git增加網絡代理和緩存(如下圖所示)
問題10:build image出現image.raw報錯
問題原因:
1、在該編譯過程中需要啟動qemu進程,此時檢查并沒有qemu進程。
2、懷疑是自己下載配置的代理proxychinas,執行命令是使用了該代理導致
執行的命令:proxychinas s2e image_build debian-9.2.1-x86_64
問題解決:
1、執行命令中刪除proxychinas即:s2e image_build debian-9.2.1-x86_64
2、正常執行時如下圖所示:
至此,s2e-env的環境搭建基本完畢。
注:在build image過程中會啟動qemu,使用xshell類似終端,可能造成失敗。
總結
以上是生活随笔為你收集整理的S2e-env环境及编译学习1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 键盘快捷指令
- 下一篇: 被社会毒打的20年毕业的后端