# reverse(逆向工程)
## 基本知識
從source code 到 執行檔會經過
1. preprocess:將library或一些定義的東西全部展開,可利用gcc -E <file.c>來查看
2. compile:將高階語言轉換成組合語言,可利用gcc -S -masm=intel <file.c>查看
3. assemble:將組合語言轉換成0101的machine code,可利用gcc -c <file.s>
4. link:將生成的object的file連接起來變為執行檔,可利用gcc <file.o>
## 基本工具
### Static analysis
- file:可以用來看file的type
- strings:會輸出file中可以輸出的字串
- 參數 -n:最小輸出字串n長度
- 參數 | grep n :抓取相關字串
- nm :會顯示compiler中的symbol
- readelf:展示關於ELF的檔案
- 參數 -a :顯示全部
- 參數 -S :只看section header
- objdump:顯示object的內容
- 參數 -M intel -d :將machine code轉為組合語言
### Dynamic analysis
- strace:可以看程式執行時call了那些系統call
- Itrace:可以看程式執行時call了那些library call
- gdb:為GNU的Debugger
- 下載:
- git clone https://github.com/longld/peda.git
~/peda
- git clone https://github.com/scwuaptx/Pwngdb.git
~/Pwngdb
- cp ~/Pwngdb/.gdbinit ~/
- 概念:可以用來即使追蹤程式,可以設置變數與設定數值
- 語法:
- break:設定斷點
- run:執行程式
- next:執行下一行
- step:進入function中(一般用next會直接做完function)
- finish:直接完成funciton
- print:輸出數值
- set:設定記憶體數值
- into break:查看斷點
- info register:查看占存器
- 相關連結:
https://gist.github.com/rkubik/b96c23bd8ed58333de
## x86-64 組合語言(intel)
### 名詞
- register(rax):用來儲存東西的(像address 或 狀態等)
- stack:儲存local variable或address的
### 語言
- mov dst src(移動)
- add,sub,imul,idiv,and,or,xor dst src(運算子)
- inc,dec,neg,not dst(只需一個參數,像加一,not)
- cmp val1,val2(比較)
- jump,ja,jb,jna,jbe,je,jne,jz label(跳到label)
- nop (不做任何事)
- syscall(系統函式呼叫)
- push,pop val
## Tips
### Patch binary
可以利用hexedit來修改machine code
### Hook function
可以用來重新定義原本function中的意義,做出新的function定義,安插在library前
## decompile 工具
- Ghidra
- IDA Pro(Hex-Rays)
以上工具可以把machine code轉為較能看得懂高階語言,同時也能做hook,patch binary或string得查找功能。但其還是有許多限制,像目前只能翻譯c和c++在x86-64下的程式,並且可能會因為compiler的優化或被加殼的原因,而造成難以看懂
- Z3-solver
可用satisfiability modulo theories,類似可以解各式邏輯問題,當我們給其一些constraint時,他會幫我們找到其符合的解
- Angr
類似IDA,但適用於各種語言(輸入為binary的檔案),他會將其轉為自己使用的語言,且為symbolic execution,且因為其含有Z3-Solver,固可以其可以解一些conditional range。
# 網路攻防戰week12 reverse
## 1

這個是先用strings顯現出內容再用grep把要的資訊擷取出來
## 2

這個是先用chmod +x 把讓檔案變成可執行的,接著用strace ./檔案 來查看其所用的system call,會發現檔案在write中,故用 strace -s 1024 使用輸出的字元增加來看到全部內容
# 網路攻防戰week13 reverse
## 1(上課展示)
```
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int foo(int a, int b)
{
puts("this is foo");
int c = a + b;
return c;
}
int main()
{
srand(time(0));
int x, y;
scanf("%d%d", &x, &y);
int out = foo(x, y);
if (out == rand() % 0x4000000)
{
puts("this is 0xdeadbeef");
}
return 0;
}
```
在這支程式中,我們輸入x,y來看其相加是否與rand() % 0x4000000的值相同,但理論上我們不可能這麼幸運能夠猜到這個答案,故我們用hook function來將其hook起來,換成其他含式。
1. 用readelf -a a.out,找出在dynsym中是否有rand這個function,可以發現在最dynsym最下面有rand,故可以利用hook function來掉包他
2. 用man 3 rand,來查找rand的prototype的形式,可以發現input式void,output是int,故等等的hook function需要與其也相同的形式
3.寫一個與rand相同prototype的library,`int rand(void)
{
return 0;
}`,並用gcc -fPIC -shared rand.c -ldl -o rand.so,將其編譯成share library,並以LD_PRELOAD=./rand.so
./a.out,這樣我們就將rand這個function被我們定義的所hook起來,這樣我們輸入時就rand的答案永遠為0(我們可以利用ldd ./a.out來看其load library的順序,故當我們寫LD_PRELOAD=./rand.so
./a.out,我們將rand.so這個library放在原本的library前面,如此一來我們就可以將其掉包)
## 常用的hookfunction
https://github.com/zardus/preeny
## 2 使用patch來得到答案
我們目前得到一個檔案,啟動後發現其要我們猜數字,故猜測這是一個猜數字然後看是否相等的遊戲。
1. 先用objdump -d guess_2 ,來看其大概做了那些操作,可以發現在2e、33的位置有call隨機的function,接下來做一連串操作,發現在8d的地方有比較,並看是否相同來跳,故猜測我們輸入的數字後,會根據cmp是否相同來看是否輸出答案,故我們可以利用patch來將75 5e(jne),改成nop,讓其直接繼續執行
2. 使用python來看nop的16進位為多少,可以得知為90,故我們可以將75 5e改成90
```
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.>>> from pwn import*
>>> context.arch = "amd64"
>>> asm("nop")
b'\x90'
```
3. 可以看到bne的位置在400b93,開啟hexedit去全找b93,並將75 5e改成90 90,在執行後,可以發現隨邊輸入數字都能獲得答案,可以看到jne被改成nop了
## 3 使用IDA + angr
1. 這題給了一個程式,先用IDA打開,可以發現其在判斷一個參數是否與2相同,相同就輸出correct,
2. 轉到組合語言看,可以發現其輸出correct後有call一個put,故我們讓程式直接跳到這個put就能得到答案,看到其從記憶體的400602開,故等等讓angr跑到那裏
3. 以下為script ,但不知為甚麼無法啟動,故最後是用一行行跑出結果
```
import angr
import claripy
project = angr.Project("./ais3_crackme-2f923b31101b28928009ceb1a816dcae")
argv1 = claripy.BVS("argv1", 100*8)
initial_state = project.factory.entry_state(
args=["./ais3_crackme-2f923b31101b28928009ceb1a816dcae", argv1]
)
sm = project.factory.simulation_manager(initial_state)
sm.explore(find=0x400602)
found = sm.found[0]
solution = found.solver.eval(argv1, cast_to=bytes)
print(repr(solution))
```

# OllyDbg
reference:[https://blog.csdn.net/eastmount/article/details/108708564](https://)
## 簡介
其為一個結合IDA與SoftICE的逆向工程軟體,其結合動態與靜態分析的軟體。
### 常用快捷鍵
1. F2 設置斷點,程序運行到此處會暫停,再按一次會刪除斷點
2. F9 開始運行程式
3. F8 一次走一步,遇到CALL不會進入子程序
4. F7 一次走一步,但會進入子程序
5. F4 運行到預選位置
6. CTRL+F9 執行到返回
## 掃雷實戰
從這裡下載掃雷遊戲[https://github.com/eastmountyxz/Reverse-Engineering-01-Saolei](https://)
1. 先將OllyDbg載入掃雷遊戲,因為遊戲開始時會呼叫視窗,故我們可以先找到BEGAINPAINT,設置breakpoint,
2. 發現BegainPaint和EndPaint中間有call別的函數,follow進入這個function中
3. 除了有開啟畫面的call外,其在遊戲進行時畫面並沒有閃爍,故猜測其利用BITBLT,設立breakpoint進入後發現其有一個雙重迴圈,且猜測掃雷遊戲是由一個二維陣列組合而成,結合這個雙重迴圈,猜測是在這裡設置雷點的位置,觀察這個程式,其一開始先將ESI歸零(用XOR自己的方式)並做比較,並用INC來加一,顧可以猜測ESI是判斷迴圈是否跳出的iterator,再看較小的迴圈發現,其call MOV EBX+ESI,而ESI再後面也有加1的動作,所以猜測EBX是一個基本位置,然後ESI來增加位置,故我們先跟進EBX的register來觀察
4. 從EBX可以觀察,10一開始出現許多,但到後面期很長才會出依次,猜測其時為圖示的邊界,而0F出現的次數比8F多,猜測8F是地雷,0F是安全的地方,實際開啟地雷遊戲後測試,發現確實在第9個位置出現地雷,並對照其他出現地雷的地方,與圖上8F的出現地方相同


## 從已知漏洞設計外掛軟件