Post

Malware ანალიზი 'NativeApp_G4QLIQRa.exe' ნაწილი #2

Malware ანალიზი 'NativeApp_G4QLIQRa.exe' ნაწილი #2

გაგრძელება

წინა პოსტში დავიწყე მავნე პროგრამის ანალიზი, რომლის გადმოწერაც სცადა ფილმების საიტმა.

როგორც პირველ ნაწილში ვთქვი, ვირუსი იწყებს Windows-ის ვერსიის შემოწმებას და პირველი if “Statement” სწორედ ვერსიის შემოწმებას ემსახურება.

1
cmp ax, 6

აქ მოწმდება eax-ის ქვედა 16 ბიტი. თუ ის 6-ის ტოლია, მაშინ 0x47aeec მეხსიერების მისამართზე შეინახება eax-ის მნიშვნელობა და CPU გადავა 0x4033df მეხსიერების მისამართზე. რა თქმა უნდა, შესაძლებელია იმის შემოწმება თუ რა ხდება ამ მეხსიერების მისამართზე.

ამ მეხსიერების მისამართზე ეს წერია:

1
mov esi, str.UXTHEME

საკმაოდ უცნაურია ეს ფაქტი. არ ვიცი UXTHEME რას შეიძლება ნიშნავდეს. არის ერთი ვარიანტი. Windows-ის დოკუმენტაციაში განხილულია Uxtheme.h ბიბლიოთეკა, რომელიც გამოიყენება Windows Theme-ის შესაცვლელად და მის მოსარგებლად.

ვფიქრობ, ფაილი Ransomeware არის და როგორც WannaCry ცვლიდა გრაფიკულ ინტერფეისს, ისე შეცვლის ეს ვირუსიც მას.

ფაზლის რაღაც ნაწილი აიწყო?

შესაძლოა ვირუსი ვინდოუსის ვერსიას იმიტომ ამოწმებს, რომ შესაბამისი ფუნქციები გამოიყენოს Uxtheme.h-დან. იმის თქმა მინდა, რომ, რა თქმა უნდა, Windows ხშირად ნახლდება და ამასთან ერთად ნახლდება მისი API, ასე, რომ შესაძლოა ჰაკერი ცდილობს დაადგინოს რომელი Windows-ის ვერსია აყენია სისტემაზე იმისათვის, რომ შეძლოს API-ს სწორად გამოყენება.

ამის შემდეგ, esi-ს მნიშვნელობა შედის სტაკზე და ხდება 0x00406624 მეხსიერების მისამართზე მყოფი ფუნქციის გამოძახება:

1.png

fcn.0x00406624

დროა ეს ფუნქცია შევისწავლო.

1.png

ფუნქციის ანალიზი

რამდენიმე ინსტრუქცია კიდევაა ქვემოთ, უბრალოდ ფოტოში არ ჩანს. მაგრამ ამას არსებითი მნიშვნელობა არ აქვს მაინც გავივლი მათ.

აქ ჩანს, რომ ამ ფუნქციას გადაეცემა ერთი არგუმენტი, რომელიც უნდა იყოს:

1
int32_t arg_8h

აქ საკმაოდ საინტერესო პროცესები ხდება. მაგალითად, eax-ში იტვირთება var_23ch-ის მეხსიერების მისამართი lea ინსტრუქციით:

1
lea eax, [var_23ch]

ეს ინსტრუქცია ნიშნავს: Load Effective Address-ს. შემდეგ, esi-ს და eax რეგისტრატორების მნიშვნელობები სტაკზე შევა და KERNEL32.dll ფაილიდან ამუშავდება GetSystemDirectoryW ფუნქცია. სტანდარტულ Windows-ის ინსტალაციაზე ამ ფუნქციამ უნდა დააბრუნოს ეს:

1
C:\Windows\System32

ეს მნიშვნელობა eax-ში უნდა გადავიდეს. უფრო სწორად, eax-ში უნდა გადავიდეს იმ ტექსტის ზომა, რაც system_directory-ში ჩაიწერა.

1
2
3
4
5
6
7
8
#include <Windows.h>

int main(void){
	WCHAR system_directory[MAX_PATH];
	UINT sizeof_answer = GetSystemDirectoryW(system_directory, MAX_PATH);

	return 0;
}

esi რეგისტრატორში კი რამდენიმე ინსტრუქციით ადრე 0x104 რიცხვი მოთავსდა, რომელიც ათობით თვლის სისტემაში გადაყვანისას აღმოჩნდება 260. იდეაში, შეგვიძლია 260 გავყოთ 2-ზე, რადგან Wide Char ნაგულისხმევად(By default) არის 2 ბაიტი ზომაში.

1
260 / 2 = 130

სტანდარტული ინსტალაციისას მიღებულ პასუხში არის 19 სიმბოლო. იმის გამო, რომ WCHAR-თან გვაქვს საქმე, ეს ორზე უნდა გავამრავლოთ:

1
19 * 2 = 38

რა თქმა უნდა, 38 ჩაეტევა 130-ში.

კარგად დაკვირვებისას ჩანს, რომ ბოლოს eax-ის მნიშვნელობა შევიდა სტაკზე. სტაკის მუშაობის პრინციპიდან გამომდინარე კი როდესაც

1
pop esi

ინსტრუქცია შესრულდება, esi-ში ჩავა წინანდელი eax-ის მნიშვნელობა, რომელიც იდეაში ზემოთ ნახსენები var_23ch ცვლადის მეხსიერების მისამართია. შემდეგ, გამოყენებულია

1
jbe 0x406648

რაც ნიშნავს იმას, რომ თუ eax-ს მნიშვნელობა ნაკლებია ან ტოლი esi რეგისტრატორის მნიშვნელობაზე, მაშინ CPU გადავა 0x406648 მეხსიერების მისამართზე,რაც გამოტოვებს

1
xor eax, eax

ინსტრუქციას. ეს ინსტრუქცია eax რეგისტრატორს გაანულებს XOR შიფრაციის ალგორითმის ლოგიკიდან გამომდინარე.

1
test eax, eax

ეს საკმაოდ საინტერესო ინსტრუქციაა და დროა ამაზე ვისაუბრო სიღრმისეულად.

მოკლედ, არსებობს ასეთი რეგისტრატორი: flags, რომელიც 32 Bit სისტემაზე გახდა eflags. ეს რეგისტრატორი ჩვეულებრივად ინახავს ინფორმაციას, მაგრამ საქმე ისაა, რომ ის ინფორმაციას უყურებს როგორც ინდივიდუალურ ბიტებს და არა როგორც ერთ მთლიან ბაიტს. ანუ, გამოდის, რომ 32-ვე ბიტი სხვადასხვა რამეს ნიშნავს.

ამ შემთხვევაში, ჩვენ გვჭირდება ZF(Zero Flag) ბიტი. test ინსტრუქცია ZF ბიტს გადააქცევს 1-ად თუ კი eax-ის მნიშვნელობა იქნება 0. თუ eax არ იქნება 0, მაშინ ZF ბიტი გახდება 0.

მის შემდეგ მყოფი ინსტრუქციაა

1
je 0x40665b

იმ შემთხვევაში თუ eax იქნება 0-ის ტოლი(ანუ ZF ბიტი ერთის ტოლი იქნება), მაშინ CPU გადახტება 0x40665b მეხსიერების მისამართზე. წინააღმდეგ შემთხვევაში, execution ჩვეულებრივად გაგრძელდება.

ამ ეტაპზე ეს ხტუნაობა უნდა გამოვტოვო, რადგან დროს მაკარგვინებს და საბოლოო ნაწილზე გადავიდე. 0x0040665e მეხსიერების მისამართზე ჯდება ყველა გადახტომა, ასე, რომ აქედან გავაგრძელებ განხილვას. DWORD შევა სტაკზე, ანუ Double Word, რომელიც არის 4 ბაიტი.

1
push dword [arg_8h]

ეს ინსტრუქცია arg_8h ცვლადის მნიშვნელობას შეიტანს სტაკზე. ამის შემდგომ ორი lea ინსტრუქციაა, რომელიც საჭრო მეხსიერების მისამართებს გამოითვლის. ამის შემდეგ wsprintfW ფუნქციაა გამოყენებული, რომელიც ასე მუშაობს:

1
wsprintfW(outBuffer, L"%ls %ls %ls", argv[1], argv[2], argv[3]);

ამ მაგალითში მოცემულია ის buffer სადაც უნდა ჩაიწეროს ტექსტი, რომელიც დაიკავებს argv მასივიდან სამი “სტრინგის” მნიშვნელობას. ანუ აეწყობა ახალი “სტრინგი”, რომელშიც გამოტოვებებით ეწერება სამი “სტრინგი”. ეს ვირუსში არ ხდება, უბრალოდ მაგალითად მოვიყვანე.

ახლა, რატომ ხდება მეხსიერების მისამართების გამოთვლა? პირველ რიგში, გამოითვლება იმ buffer-ის მეხსიერების მისამართი, სადაც უნდა ჩაიწეროს ტექსტი.

შემდეგ გამოითვლება მეორე მეხსიერების მისამართი, რომელიც ალბათ მესამე პარამეტრის მეხსიერების მისამართი უნდა იყოს. გამოთვლილი მისამართები ნაწილდებიან ecx და eax რეგისტრატორებში, რის შემდეგაც ამ ორი რეგისტრატორის მნიშვნელობები სტაკზე შედის str._s_S.dll-თან ერთად, რომელიც მეორე პარამეტრი უნდა იყოს წესით. ამის შემდეგ იძახებს CPU იმ ფუნქციას, რომელიც ზემოთ განვიხილე.

საბოლოო ჯამში, იწყობა რომელიღაც dll ფაილის ე.წ. path.

ამ ყველაფრის შემდეგ, fcn.0x00406624-ის ბოლოს ხდება LoadLibraryExW ფუნქციის გამოძახება, რომელიც DLL ფაილს ტვირთავს.

“fcn.0x00406624”-ის შეჯამება

მოკლედ რომ ვთქვა, ეს ფუნქცია იღებს სისტემის დირექტორიას, რომელიც სტანდარტულად უნდა იყოს

1
C:\Windows\System32

და ამის შემდეგ მან უნდა გამოითვალოს რომელიღაც dll ფაილის ლოკაცია, რომელიც ჩაიტვირთება ფუნქციის ბოლოს.

This post is licensed under CC BY 4.0 by the author.