taibeihacker
Moderator
0x00 概述
目標站點是http://www.example.com,官網提供了api使用文檔,但是對其測試後沒有發現漏洞,目錄、端口掃描等都未發現可利用的點。後發現官網提供了客戶端下載,遂對其進行一番測試。0x01 信息收集
先抓了下客戶端的包,使用Fiddler和BurpSuite都抓不到,懷疑走的不是HTTP協議,用WireShark查看其確實用的是HTTP協議,但是數據包不好重放,這裡最後使用了WSExplorer抓指定進程的包,成功抓取到通信的數據,抓到的數據如下,綠色的是請求包,紅色的是響應包。
數據包又分為兩部分,一個是請求行和請求頭。

一個是請求正文。

拼接起來即可放到BurpSuite中進行數據包的重放

0x03 测试过程
可看到請求包經過了加密再傳輸,返回的響應包也經過了加密。但是加解密總歸是在客戶端進行的,所以可從分析客戶端入手。使用Exeinfo PE查殼,可得知使用的是.NET框架C#開發的程序。

可以使用dnspy,針對.NET程序的逆向工程工具,對客戶端的加解密進行分析。打開後發現類及方法的命名都是無規律的數字字母,代碼做了混淆。

混淆了的代碼不利用閱讀分析,可使用De4Dot嘗試反混淆,支持很多種混淆加密工具混淆過的源碼。
de4dot-x64.exe origin.exe
即可得到反混淆後的程序origin-cleaned.exe

將反混淆後的程序拖入dnspy查看,可看到基本已還原,提高了可讀性。

因為其通信採用的是HTTP協議,又發現有個類名為HttpHelper,跟進分析,代碼不多看到一個Post函數,疑似為對數據加密並發起Post請求的方法,如圖。

調用了MM.Encrypt()對請求的參數進行加密,跟進方法,發現其中關鍵的加密函數應該就是MM類下的test05函數。

下斷點,驗證程序是否調用此函數進行加密並傳輸,我在明文及密文處下了斷點。

F5啟動程序,輸入賬號密碼test123456,登錄。

程序在斷點處停了下來,明文中包含我輸入的賬號test123456和md5加密過的密碼。

放行,得到經過加密的內容,可確定就是調用了此處的加密函數。

後又證實響應包解密調用的是MM類下的test06函數,請求包加密函數test05及響應包解密函數test06都是調用Dll中對應的函數。

此處加解密調用的是兩套方法,不能用解密函數去解密請求包加密後的數據。為了方便測試,以及快速加解密,將其加解密函數扣出來,同樣調用Dll裡的函數,編譯成一個獨立的程序,這樣也不用分析算法。
這裡我使用的是SharpDevelop編譯的,使用Visual Studio總是會報錯…
public static string decryptResponse(string cipher){
byte[] bytes=Encoding.UTF8.GetBytes(cipher);
byte[] array=new byte[bytes.Length + 128];
int count=Program.test06(ref bytes[0], ref array[0]);
string text=Encoding.UTF8.GetString(array, 0, count);
return text;
}
public static string encryptRequest(string plain){
byte[] bytes=Encoding.UTF8.GetBytes(plain);
int num=bytes.Length * 2 + 128;
if(num32){
num=64;
}
byte[] array=new byte[num];
int num2=0;
num2=test05(ref bytes[0], ref array[0]);
string result=Encoding.UTF8.GetString(array, 0, num2);
return result;
}
加密

解密

再用Python的Flask框架在本地寫一個代理轉發程序,方便在BurpSuite中進行重放測試。
流程如下:
本地發送明文數據包到代理代理接收到請求包調用程序對請求包進行加密將加密後的數據包轉發給服務器調用程序對服務器返回的內容解密返回給明文數據到本地from flask import request, Flask
from urllib.parse import quote
import requests
import os
headers={
'User-Agent': 'Mozilla',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'gzip, deflate',
}
app=Flask('example')
@app.route('/example', methods=['POST'])
def proxy():
form=request.form
request_plain=''
for key in form:
request_plain +='{}={}'.format(key, form[key])
response_plain=test(request_plain)
return response_plain
def encrypt(filename):
encrypt_cmd='crypto.exe -encrypt {}'.format(filename) #要加密的內容從文件讀取
result=os.popen(encrypt_cmd) # 執行exe
request_cipher=quote(result.read()) #加密後的內容經過一次url編碼把+ 號轉成%2B 服務端才能識別
return request_cipher
def decrypt(filename):
decrypt_cmd='crypto.exe -decrypt {}'.format(filename) #要解密的內容從文件讀取
result=os.popen(decrypt_cmd) # 執行exe
response_plain=result.read() # 讀取解密後的內容
return response_plain
def test(request_plain):
url='http://example.com/api/'
plain_txt='plain.txt'
with open(plain_txt, 'w') as f1:
f1.writelines(request_plain) # 存放明文到plain.txt
request_cipher=encrypt(plain_txt) # 加密明文
response=requests.post(url=url, data=request_cipher, headers=headers) #發送請求
cipher_txt='cipher.txt'
with open(cipher_txt, 'w') as f2:
f2.writelines(response.text) #存放密文到cipher.txt
response_plain=decrypt(cipher_txt) # 解密密文
return response_plain
if __name__=='__main__':
app.run(host='0.0.0.0', port=9999, debug=True)
這裡每次請求的接口都是一樣的,改變的只是請求體中的參數。在CodeService中有所有接口的明文,全部提取出來。

即可正常的在BurpSuite中進行測試~

最後成功在一個接口中發現SQL注入。

0x04 总结
1.通過WSExplorer抓指定進程的包,發現http協議的數據包已加密2.使用Exeinfo PE查殼,可得知使用的是.NET框架C#開發的程序3.使用dnspy對程序進行反編譯,發現源碼已混淆加密4.使用De4Dot嘗試反混淆,支持很多種混淆加密工具混淆過的源碼de4dot-x64.exe origin.exe5.再次使用dnspy對程序進行反編譯,然後查看到程序加密的函數方法,對其斷點,然後按F5運行,程序在斷點處停了下來,明文中包含我輸入的賬號test123456和md5加密過的密碼。 6.找到程序的加密和解密函數段,將其主要代碼摳出來,使用python編寫7.再用Python的Flask框架在本地寫一個代理轉發程序,方便在BurpSuite中進行重放測試。流程如下:本地發送明文數據包到代理代理接收到請求包調用程序對請求包進行加密將加密後的數據包轉發給服務器調用程序對服務器返回的內容解密返回給明文數據到本地原文連接:https://blog.csdn.net/qq_32727277/article/details/102783316