前幾天有位朋友在微信上找到我,說他的一個程式上了生產之後,被運維監控定位到這個程式會向一個網址為: http://m.365ey.net
上不定期打資料,而且還是加密的格式,要他解釋到底是怎麼回事?朋友說根本不認識這個網址,最後在恐慌中排查到是專案中參照了 DeveloperSharp.RabbitMQ
元件所致,截圖如下:
朋友反編譯了下sdk原始碼,發現都是混淆過的沒法看,聊的過程中朋友很恐慌,很焦慮,擔心生產的資料被洩漏,讓我幫忙看下是否有手段定位下到底都採集了什麼資料?
說實話,這種事情聽起來就很驚魂,情從肺腑出,方能入肺腑。。。只要是一個正能量的人,這個忙肯定是盡最大可能的幫一下。
從 nuget 中把 DeveloperSharp.RabbitMQ
下載下來,寫好一個測試案例。
internal class Program
{
static void Main(string[] args)
{
for (int i = 0; i < int.MaxValue; i++)
{
try
{
var queueName = "jk";
var content = $" hello world! {i}";
RabbitMQHelper.SendMessage(queueName, content);
Console.WriteLine($"時間:{DateTime.Now}, i={i} 次處理!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Thread.Sleep(1000);
}
}
}
}
為了安全,我把程式放到虛擬機器器中,同時在 hosts 下給它設定個錯誤的 ip 地址。
192.168.1.30 m.365ey.net
接下來開啟 Fiddler,再用 WinDbg TTD
的方式把程式啟動起來來記錄程式的全部行為,方便我後續分析,
正如朋友所說,真的有采集行為:
http://m.365ey.net:13064/AssistLog.svc
http://m.365ey.net:13063/QueryLog.svc
截獲請求的程式碼很簡單,因為遮蔽了 IP,所以請求肯定會拋異常,我只需要用 sxe clr
攔截下 First Chance Exception
就能捕獲到呼叫程式碼。
0:013> sxe clr
0:013> g
(3398.3f7c): CLR exception - code e0434352 (first/second chance not available)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
Time Travel Position: 16D93B:0
eax=079befe8 ebx=00000005 ecx=00000005 edx=00000000 esi=079bf0a8 edi=00000001
eip=77207380 esp=079befe0 ebp=079bf040 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000216
ntdll!RtlRaiseException:
77207380 55 push ebp
0:013> !clrstack
OS Thread Id: 0x3f7c (13)
Child SP IP Call Site
079bf0fc 77207380 [HelperMethodFrame: 079bf0fc]
079bf1ac 78861902 System.Net.HttpWebRequest.GetResponse() [f:\dd\NDP\fx\src\net\System\Net\HttpWebRequest.cs @ 2254]
079bf1fc 0a5a2e89 System.ServiceModel.Channels.HttpChannelFactory`1+HttpRequestChannel+HttpChannelRequest[[System.__Canon, mscorlib]].WaitForReply(System.TimeSpan)
079bf24c 0a5a1199 System.ServiceModel.Channels.RequestChannel.Request(System.ServiceModel.Channels.Message, System.TimeSpan)
079bf2c0 0a5a1026 System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message, System.TimeSpan)
079bf2d0 0a5703f3 System.ServiceModel.Channels.ServiceChannel.Call(System.String, Boolean, System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[], System.TimeSpan)
079bf3cc 0a57010d System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage, System.ServiceModel.Dispatcher.ProxyOperationRuntime)
079bf3f8 0a56f79e System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)
079bf438 7b224e24 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32) [f:\dd\ndp\clr\src\BCL\system\runtime\remoting\realproxy.cs @ 823]
079bf5d0 7a5df148 [TPMethodFrame: 079bf5d0] wfP8f24Vyfpc8suOyj.bBZbSsm9FOwaYWDWVc.Record1(System.String, System.String, System.String, System.String, System.String, System.String, System.String)
079bf644 067c835f System.Base.ApplicationContext+c.b__19_0()
079bf6b0 7b1dd4bb System.Threading.Tasks.Task.InnerInvoke() [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Task.cs @ 2884]
...
從執行緒棧看,請求 http://m.365ey.net:13064/AssistLog.svc
是由 Record1
方法發起的,一看就是個 WCF 方法,引數名稱和個數都和 Fiddler 中保持一致, 截圖如下:
要找到原引數資訊,需要找到是誰呼叫了 Record1
方法,可以用 !U 067c835f
檢視函數組合程式碼,簡化後如下:
0:013> !U 067c835f
Normal JIT generated code
System.Base.ApplicationContext+<>c.<HashObjectMap>b__19_0()
Begin 067c7ed8, size 584
...
067c8333 8b3d74361904 mov edi,dword ptr ds:[4193674h] (Object: System.Runtime.Remoting.Proxies.__TransparentProxy)
067c8339 ff75b0 push dword ptr [ebp-50h]
067c833c ff75ac push dword ptr [ebp-54h]
067c833f ff75a8 push dword ptr [ebp-58h]
067c8342 ff75a4 push dword ptr [ebp-5Ch]
067c8345 ff75a0 push dword ptr [ebp-60h]
067c8348 b94e080000 mov ecx,84Eh
067c834d ff15b05d7a06 call dword ptr ds:[67A5DB0h] (System.Base.ApplicationContext+<>c.zmMLEYhjSCTVEl2CxBD(Int32), mdToken: 0600009e)
067c8353 50 push eax
067c8354 8b55b4 mov edx,dword ptr [ebp-4Ch]
067c8357 8bcf mov ecx,edi
067c8359 ff15d8016d00 call dword ptr ds:[6D01D8h]
...
原來是 <HashObjectMap>b__19_0
方法做的呼叫,也就是 call dword ptr ds:[6D01D8h]
,不信的話可以截圖看原始碼:
從混淆的程式碼看,有幾個特徵:
等等,那怎麼提取呢? 這裡只演示一個 aa 引數吧,可以在組合程式碼的第一個 x4phG7d0qxdP1ZxlQa.pliOsRbOU
方法上下一個斷點,即 067c820b
處觀察方法引數,下斷點後,讓程式迴流。
0:013> !U 067c8359
Normal JIT generated code
System.Base.ApplicationContext+<>c.<HashObjectMap>b__19_0()
...
067c8206 50 push eax
067c8207 8bd3 mov edx,ebx
067c8209 8bcf mov ecx,edi
067c820b ff15e8667a06 call dword ptr ds:[67A66E8h] (System.Base.ApplicationContext+x4phG7d0qxdP1ZxlQa.pliOsRbOU(System.String, System.String, System.String), mdToken: 0600003e)
067c8211 8945b4 mov dword ptr [ebp-4Ch],eax
...
0:013> bp 067c820b
0:013> g-
Breakpoint 1 hit
Time Travel Position: 117A27:A80
eax=032c0ca4 ebx=032bf94c ecx=0329e558 edx=032bf94c esi=032bea78 edi=0329e558
eip=067c820b esp=079bf640 ebp=079bf6a8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
067c820b ff15e8667a06 call dword ptr ds:[67A66E8h] ds:002b:067a66e8=067cdf00
0:013> ub 067c820b
067c81ef 8945b8 mov dword ptr [ebp-48h],eax
067c81f2 8b3d68361904 mov edi,dword ptr ds:[4193668h]
067c81f8 8b5e08 mov ebx,dword ptr [esi+8]
067c81fb b914040000 mov ecx,414h
067c8200 ff15b0647a06 call dword ptr ds:[67A64B0h]
067c8206 50 push eax
067c8207 8bd3 mov edx,ebx
067c8209 8bcf mov ecx,edi
上面輸出的 ecx, edx, eax
分別就是 pliOsRbOU()
方法的三個引數。
0:013> !do ecx
Name: System.String
MethodTable: 7ad924e4
EEClass: 7ae97690
Size: 40(0x28) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: 192.168.0.106
Fields:
MT Field Offset Type VT Attr Value Name
7ad942a8 4000283 4 System.Int32 1 instance 13 m_stringLength
7ad92c9c 4000284 8 System.Char 1 instance 31 m_firstChar
7ad924e4 4000288 70 System.String 0 shared static Empty
>> Domain:Value 00b0bce8:NotInit <<
0:013> !do edx
Name: System.String
MethodTable: 7ad924e4
EEClass: 7ae97690
Size: 46(0x2e) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: N8CDEFGH+JKLM..P
Fields:
MT Field Offset Type VT Attr Value Name
7ad942a8 4000283 4 System.Int32 1 instance 16 m_stringLength
7ad92c9c 4000284 8 System.Char 1 instance 4e m_firstChar
7ad924e4 4000288 70 System.String 0 shared static Empty
>> Domain:Value 00b0bce8:NotInit <<
0:013> !do eax
Name: System.String
MethodTable: 7ad924e4
EEClass: 7ae97690
Size: 32(0x20) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: TripleDES
Fields:
MT Field Offset Type VT Attr Value Name
7ad942a8 4000283 4 System.Int32 1 instance 9 m_stringLength
7ad92c9c 4000284 8 System.Char 1 instance 54 m_firstChar
7ad924e4 4000288 70 System.String 0 shared static Empty
>> Domain:Value 00b0bce8:NotInit <<
從輸出中可以看到,aa 引數原來提取了我的 ip 地址,用同樣的方式可以提取出所有的方法引數,這裡就不詳述了,我做了一個整理,截圖如下:
從圖中可以看到: AssistLog.svc
請求大概會提取:
用同樣的方式調查請求 http://m.365ey.net:13063/QueryLog.svc
,整理如下:
這個請求中主要統計了一些介面版本等資訊,並沒有發現有訊息的外洩,分析到這裡還是比較欣慰的,將資訊反饋給朋友,讓朋友不要擔心,應該不會有問題。
總的來說我還是非常相信作者,寫一個 SDK 已經夠辛苦了,做一些違法犯罪的事情道理上說不通,作者也就是純技術心,想收集下使用者端的使用情況,不過在未經許可的情況下確實有所不妥,但初心不壞。
如果 SDK 的作者能夠幫他的使用者解答疑惑,讓他的粉絲群體可以安心使用,那就更好了,在此感謝作者的辛苦付出,祝元件越來越強大。