Ручная троянизация TLS

Намедни товарищ попросил сделать странную задачку:
-на вход exe-файл
-на выход он же, но не работающий где либо кроме съемных носителей.

Вараниты решения:
-Дроппер извлекающий файл в %temp% и запускающий по WinExec – после проверки расположения файла – любой школьник с ProcessHacker вытянет оригинальный файл – не подходит.

-PeLoader запускающий файл в памяти – звучит нормально, но могут быть проблемы с детектами ав. Не работает. Причина?
1)Забыл скопировать оверлей – решается копированием в запакованной и удаленим с оригинала
2)tls – решается заменой лоадера на RunPe
Всё бы ничего, но из-за хранения оригинального образа в ресурсах 12 детектов ав, которые нужно убрать. Файл легальный и должен лежать годами, так что вариант с криптором отметаем.

-Заражение файла. Отличная идея – но в секции кода свободно всего 140 байт, как избежать детекта ав и уместить все проверки?
1)минимальный размер – написание компактного шелл-кода:

;114 bytes
loader_shell:
;GetDriveType
mov edi,'evir'
call get_addr
push 0
call eax
cmp eax,2
je exits
 
;ExitProcess
mov edi,'corP'
call get_addr
push 0 
call eax
 
exits:
ret 3*4; tls stub
 
get_addr:
PUSH ESI
XOR EDX,EDX
MOV DL,30h
assume fs:nothing
MOV EDX,DWORD PTR FS:[EDX]
MOV EDX,DWORD PTR DS:[EDX+0Ch]
MOV EDX,DWORD PTR DS:[EDX+1Ch]
next_lib:
MOV EAX,DWORD PTR DS:[EDX+8h]
MOV ESI,DWORD PTR DS:[EDX+20h]
MOV EDX,DWORD PTR DS:[EDX]
CMP BYTE PTR DS:[ESI+0Ch],33h
JNZ next_lib ;kernel32
MOV EBX,EAX
ADD EBX,DWORD PTR DS:[EAX+3Ch]
MOV EDX,DWORD PTR DS:[EBX+78h]
ADD EDX,EAX
MOV EBX,DWORD PTR DS:[EDX+20h]
ADD EBX,EAX
XOR ECX,ECX
next_api2:
MOV ESI,DWORD PTR DS:[EBX+ECX*4]
ADD ESI,EAX
INC ECX
CMP DWORD PTR DS:[ESI+4],edi
JNZ next_api2
MOV EBX,DWORD PTR DS:[EDX+24h]
ADD EBX,EAX
MOV CX,WORD PTR DS:[EBX+ECX*2]
MOV EBX,DWORD PTR DS:[EDX+1Ch]
ADD EBX,EAX
MOV EBX,DWORD PTR DS:[EBX+ECX*4-4]
ADD EAX,EBX
POP ESI
db 0c3h

Если взглянуть на код, вызывающий callback:

 
76F489C4   55               PUSH EBP
76F489C5   8BEC             MOV EBP,ESP
76F489C7   56               PUSH ESI
76F489C8   57               PUSH EDI
76F489C9   53               PUSH EBX
76F489CA   8BF4             MOV ESI,ESP
76F489CC   FF75 14          PUSH DWORD PTR SS:[EBP+14]
76F489CF   FF75 10          PUSH DWORD PTR SS:[EBP+10]
76F489D2   FF75 0C          PUSH DWORD PTR SS:[EBP+C]
76F489D5   FF55 08          CALL DWORD PTR SS:[EBP+8]
76F489D8   8BE6             MOV ESP,ESI ; <-
76F489DA   5B               POP EBX
76F489DB   5F               POP EDI
76F489DC   5E               POP ESI
76F489DD   5D               POP EBP
76F489DE   C2 1000          RETN 10

Заметим, что нельзя изменять регистр ESI, похожие ограничения есть и при вызове DLLMain.

2)Внедрение в файл – ну тут либо делать траплин (jmp) от начала кода в конец секции, что даст хуеву тучу детектов, либо перехватывать все CALL, с последующим восстановлением – в 140 байт никак не сделать.

На помощь приходит то что мешало при сырой загрузке – TLS, который мы запросто “заражаем”:
1)перед Шк делаем структуру-Callbacks:

DWORD VA_of_shellcode
DWORD 0

2)правим tls – Address of Callbacks на адрес нашей структуры.
3)всегда оставляю перед ШК один свободный байт, чтобы можно был поставить там int3 (0cch), а после тестов затереть nop (90h).

Тестируем. Работает)

One thought on “Ручная троянизация TLS

Добавить комментарий