HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > ПРОГРАММИРОВАНИЕ > С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 08.02.2023, 20:07
colby57
Новичок
Регистрация: 13.02.2022
Сообщений: 12
С нами: 2236305

Репутация: 28
По умолчанию

Шалом, это мой первый тред на борде.

И решил немного доработать старый исходник, который проходится по функциям IAT (Import Address Table), проверяя их на опкоды джампа, и брейкпоинтов x32dbg (int3, int 0x3, ud2), Ordinal, кстати, он не проверяет, но можете допилить за меня

Такой приём будет очень полезен против новичков в вашем лоадере, которые любят ставить бряки куда попало без предварительного динамического анализа защиты

Для незнающих скажу, что если ваша функция накрыта виртуализацией кода, которая за собой как бонус будет вызывать функцию по своему функцию и и на этот адрес нет никаких других внешних вызовов в вашей программе, то этот чек пользователь спокойно пройдет, поскольку данной функции не будет в IAT.

Вот и сам исходник:

IATScan.hpp:





Код:
#pragma once
#include 
#include 
#include 
#include 
namespace
Engine
{
struct
S_CorruptedFunction
{
std
::
string m_cModuleName
;
std
::
string m_cFunctionName
;
std
::
uintptr_t m_pAddress
;
S_CorruptedFunction
(
std
::
string cModule
,
std
::
string cFunc
,
std
::
uintptr_t pAddress
)
:
m_cModuleName
(
std
::
move
(
cModule
)
)
,
m_cFunctionName
(
std
::
move
(
cFunc
)
)
,
m_pAddress
(
std
::
move
(
pAddress
)
)
{
}
}
;
inline
BYTE bInt3Breakpoint
=
0xCC
;
inline
BYTE bJumpOpcode
=
0xE9
;
inline
WORD wUd2Breakpoint
=
0x0B0F
;
inline
WORD wInt3Breakpoint
=
0x03CD
;
inline
std
::
vector

m_cCorruptedFunctions
{
}
;
void
OutputCorruptedFunctions
(
)
;
void
AddFunction
(
const
S_CorruptedFunction
&
cCorruptedFunctions
)
;
bool
IATScan
(
)
;
}


IATScan.cpp:





Код:
#include "IATScan.hpp"
void
Engine
::
OutputCorruptedFunctions
(
)
{
if
(
m_cCorruptedFunctions
.
empty
(
)
)
{
printf
(
"[~] No corrupted functions found!\n"
)
;
return
;
}
for
(
const
auto
&
Iterator
:
m_cCorruptedFunctions
)
printf
(
"[!] Module: %s\tFunction: %s\tAddress: 0x%p\n"
,
Iterator
.
m_cModuleName
.
c_str
(
)
,
Iterator
.
m_cFunctionName
.
c_str
(
)
,
Iterator
.
m_pAddress
)
;
}
void
Engine
::
AddFunction
(
const
S_CorruptedFunction
&
cCorruptedFunctions
)
{
m_cCorruptedFunctions
.
push_back
(
cCorruptedFunctions
)
;
}
bool
Engine
::
IATScan
(
)
{
LPVOID lpBaseAddress
=
(
LPVOID
)
GetModuleHandle
(
NULL
)
;
PIMAGE_DOS_HEADER pDosHeader
;
PIMAGE_NT_HEADERS pNtHeader
;
IMAGE_OPTIONAL_HEADER pOptionalHeader
;
IMAGE_DATA_DIRECTORY pImportDirectory
;
DWORD dwStartRVA
;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor
;
pDosHeader
=
(
PIMAGE_DOS_HEADER
)
lpBaseAddress
;
if
(
pDosHeader
->
e_magic
!=
IMAGE_DOS_SIGNATURE
)
return
false
;
pNtHeader
=
(
PIMAGE_NT_HEADERS
)
(
(
DWORD_PTR
)
lpBaseAddress
+
pDosHeader
->
e_lfanew
)
;
if
(
pNtHeader
->
Signature
!=
IMAGE_NT_SIGNATURE
)
return
false
;
pOptionalHeader
=
pNtHeader
->
OptionalHeader
;
pImportDirectory
=
pOptionalHeader
.
DataDirectory
[
IMAGE_DIRECTORY_ENTRY_IMPORT
]
;
dwStartRVA
=
pImportDirectory
.
VirtualAddress
;
pImportDescriptor
=
(
PIMAGE_IMPORT_DESCRIPTOR
)
(
(
DWORD_PTR
)
lpBaseAddress
+
dwStartRVA
)
;
if
(
pImportDescriptor
==
NULL
)
return
false
;
DWORD dwIndex
=
-
1
;
while
(
pImportDescriptor
[
++
dwIndex
]
.
Characteristics
!=
0
)
{
PIMAGE_THUNK_DATA pOriginalFirstThunk
;
PIMAGE_THUNK_DATA pFirstThunk
;
char
*
pDllName
=
(
char
*
)
(
(
DWORD_PTR
)
lpBaseAddress
+
pImportDescriptor
[
dwIndex
]
.
Name
)
;
HMODULE hModule
=
GetModuleHandleA
(
pDllName
)
;
pOriginalFirstThunk
=
(
PIMAGE_THUNK_DATA
)
(
(
DWORD_PTR
)
lpBaseAddress
+
pImportDescriptor
[
dwIndex
]
.
OriginalFirstThunk
)
;
pFirstThunk
=
(
PIMAGE_THUNK_DATA
)
(
(
DWORD_PTR
)
lpBaseAddress
+
pImportDescriptor
[
dwIndex
]
.
FirstThunk
)
;
if
(
pOriginalFirstThunk
==
nullptr
||
pFirstThunk
==
nullptr
)
return
false
;
while
(
pOriginalFirstThunk
->
u1
.
AddressOfData
)
{
if
(
!
(
pOriginalFirstThunk
->
u1
.
Ordinal
&
IMAGE_ORDINAL_FLAG
)
)
{
PIMAGE_IMPORT_BY_NAME pImageImport
=
(
PIMAGE_IMPORT_BY_NAME
)
(
(
LPBYTE
)
lpBaseAddress
+
pOriginalFirstThunk
->
u1
.
AddressOfData
)
;
auto
pFn
=
GetProcAddress
(
hModule
,
(
LPCSTR
)
pImageImport
->
Name
)
;
if
(
(
*
(
BYTE
*
)
pFn
==
bInt3Breakpoint
||
*
(
BYTE
*
)
pFn
==
bJumpOpcode
)
||
(
*
(
WORD
*
)
pFn
==
wUd2Breakpoint
||
*
(
WORD
*
)
pFn
==
wInt3Breakpoint
)
)
{
Engine
::
AddFunction
(
S_CorruptedFunction
(
std
::
string
(
pDllName
)
,
std
::
string
(
pImageImport
->
Name
)
,
(
std
::
uintptr_t
)
pFn
)
)
;
}
}
pFirstThunk
++
;
pOriginalFirstThunk
++
;
}
}
return
true
;
}


Пример его использования:

Entry.cpp:





Код:
#include "IATScan.hpp"
int
main
(
)
{
printf
(
"t.me/colby5engineering\n\n"
)
;
if
(
Engine
::
IATScan
(
)
==
true
)
Engine
::
OutputCorruptedFunctions
(
)
;
else
printf
(
"[-] Failed to scan iat :(\n"
)
;
std
::
cin
.
get
(
)
;
return
0
;
}


Результат использования функции:

1675872223136.pngcolby57 · 8 Фев 2023 в 19:07' data-fancybox="lb-post-1252723" data-lb-caption-extra-html="" data-lb-sidebar-href="" data-single-image="1" data-src="https://www.blast.hk/attachments/189178/" style="cursor: pointer;" title="1675872223136.png">


Также забыл сказать, что функция _initialize_narrow_environment будет находится в списке, поскольку первый её байт - это 0xE9. Для неё можно спокойно сделать проверку.

Полный исходный код находится на гитхабе: https://github.com/colby57/IAT-Scanner

Всем пока!
 
Ответить с цитированием

  #2  
Старый 08.02.2023, 20:12
digitalpurple
Познающий
Регистрация: 29.03.2022
Сообщений: 99
С нами: 2174010

Репутация: 33
По умолчанию

нус, тема бомба, добро пожаловать
 
Ответить с цитированием

  #3  
Старый 08.02.2023, 20:16
arkwhtp
Новичок
Регистрация: 08.02.2023
Сообщений: 2
С нами: 1717811

Репутация: 3
По умолчанию

Годно
 
Ответить с цитированием

  #4  
Старый 09.02.2023, 00:13
kin4stat
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами: 4483143

Репутация: 183


По умолчанию

Много чего не учтено. По хорошему тут чуть ли не эмулятор прикручивать надо. Тот же long jmp игнорируется(ff 25).

Можно например сделать вообще что-нибудь типа

Код:





Код:
xor eax, eax
jno code

code:
int 3


Но против нубов спасет, да. Только по хорошему сюда еще проверку региона на PAGE GUARD прикрутить
 
Ответить с цитированием

  #5  
Старый 09.02.2023, 03:57
F0RQU1N and
Познавший АНТИЧАТ
Регистрация: 29.09.2018
Сообщений: 1,292
С нами: 4012500

Репутация: 138


По умолчанию

О колби на бластхак пришел, ку
 
Ответить с цитированием

  #6  
Старый 09.02.2023, 08:31
colby57
Новичок
Регистрация: 13.02.2022
Сообщений: 12
С нами: 2236305

Репутация: 28
По умолчанию

Цитата:
Сообщение от kin4stat  

Можно например сделать вообще что-нибудь типа
Пример неуместный

Если ты ещё не понял, то есть разница между бряком, который вписываешь ты, и бряком который ставит непосредственно сам дебаггер.

В твоём примере я вижу, что бряк вписываешь именно ты

У дебаггера есть 4 вида бряков: хардвейр в виде 4 штук, int3, ud2 и int 0x3, который как раз ты и поставил.

При выполнении данного кода ты поймаешь краш с исключением EXCEPTION_BREAKPOINT, поскольку отладчик будет обрабатывать только опкоды бряков, которые он сам выставил. Можешь конечно сам модифицировать отладчик, и вместо условного int 0x3, который ты показал можешь поменять на тот асм-код, который ты решил предоставить в своём примере, но произойдет нечто страшное))

Да и где тут вообще восстановление регистра eax? Ты просто контекст ломаешь, а если у меня в eax важный аргумент лежит с поинтером, который ты затёр?

Раз уже показываешь пример, то показывай правильный, ака:

Код:





Код:
push eax
xor eax, eax
jno code

code:
nop

pop eax


Цитата:
Сообщение от kin4stat  

Тот же long jmp игнорируется(ff 25).
Никто не спорит, ведь в теме я упомянул как раз о том, что мой исходник это лишь пример того, как можно обнаруживать бряки или релативный джамп, и ещё упомянул, что ничего не мешает добавлять свои детекты

Цитата:
Сообщение от kin4stat  

Но против нубов спасет, да. Только по хорошему сюда еще проверку региона на PAGE GUARD прикрутить
Опять же, ответ выше

Можно долго спорить о том, чего у меня не хватает в коде, и какие меры предпринимать по обходу этого. Сам я мог бы это обойти как раз 1 хардвейр бряком на любую функцию из IAT, но тем не менее я уже объяснил, что против новичков такое сработает, да и люди в основном абузят MinHook и в x86 и в x64 в наглую, где как раз в начале хукнутой функции будет установлен угадай что? Релативный джамп, т.е. первый байт у тебя будет 0xE9 Поэтому в любом случае даже если не улучшать детекты в моём исходнике, то детектов будет предостаточно, чтобы отсеивать новичков.
 
Ответить с цитированием

  #7  
Старый 09.02.2023, 20:15
kin4stat
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами: 4483143

Репутация: 183


По умолчанию

Цитата:
Сообщение от colby57  

При выполнении данного кода ты поймаешь краш с исключением EXCEPTION_BREAKPOINT, поскольку отладчик будет обрабатывать только опкоды бряков, которые он сам выставил.
От отладчика все же зависит. Ну и кстати этот эксепшен скипается легко

Цитата:
Сообщение от colby57  

Да и где тут вообще восстановление регистра eax? Ты просто контекст ломаешь, а если у меня в eax важный аргумент лежит с поинтером, который ты затёр?
Раз уже показываешь пример, то показывай правильный, ака:
Это псевдокод все же был, а не реальный пример. Очевидно что регистр не сохранен.
 
Ответить с цитированием

  #8  
Старый 11.02.2023, 12:10
colby57
Новичок
Регистрация: 13.02.2022
Сообщений: 12
С нами: 2236305

Репутация: 28
По умолчанию

Цитата:
Сообщение от kin4stat  

От отладчика все же зависит. Ну и кстати этот эксепшен скипается легко
чего?)))

Нет, ну если ты написал свой дебаггер, который по всем параметрам превосходит x64dbg, который обновляют часто, то тут прям моё увожение, однако я повторяю тебе еще раз, x64dbg на сегодняшний момент является самым стабильным и актуальным отладчиком в юзермоде, но тем не менее, хендлить бряки, которые ставят удаленно с дллки или в самом дебаггере прописывая инт3 в ручную он не умеет, что приводит к... о боже мой!



Первая строка это то, как x64dbg сам ставит дебаггер по кнопочке F2, а другие строчки это попытки дебаггера обработать инт3, который пренадлежит не ему

Да и что значит твоё "легко скипается"? Понятное дело, что если ты свой вех поставишь, то сможешь сам проскипать, только я не понимаю к чему это мне было писать)

Цитата:
Сообщение от kin4stat  

Это псевдокод все же был, а не реальный пример. Очевидно что регистр не сохранен.
Ну, раз ты решил докапываться до моей идеи, то и я буду преследовать ту же цель в твоих ответах мне

Бля, мужик..

Если пытаешься меня чему-то учить (будучи зная меньше чем я), то хотя бы выписывай правильно примеры, отговариваться по типу "это просто псевдокод" не нужно, если бы в дебаггере вместо инт3 юзался твой код, бедные реверсеры бы каждый день тебе отписывали с баг-репортом, что контекст их программы каким-то чудом умудрился сломаться...

Найдешь к чему ещё прикопаться, или закончим наш чудесный диалог?
 
Ответить с цитированием

  #9  
Старый 12.02.2023, 00:07
kin4stat
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами: 4483143

Репутация: 183


По умолчанию

Цитата:
Сообщение от colby57  

чего?)))
Нет, ну если ты написал свой дебаггер, который по всем параметрам превосходит x64dbg, который обновляют часто, то тут прям моё увожение, однако я повторяю тебе еще раз, x64dbg на сегодняшний момент является самым стабильным и актуальным отладчиком в юзермоде, но тем не менее, хендлить бряки, которые ставят удаленно с дллки или в самом дебаггере прописывая инт3 в ручную он не умеет, что приводит к... о боже мой!



Первая строка это то, как x64dbg сам ставит дебаггер по кнопочке F2, а другие строчки это попытки дебаггера обработать инт3, который пренадлежит не ему

Да и что значит твоё "легко скипается"? Понятное дело, что если ты свой вех поставишь, то сможешь сам проскипать, только я не понимаю к чему это мне было писать)
Или можно просто Ctrl+F8 нажать. Тоже работает.

Думаю вопрос исчерпан.

Цитата:
Сообщение от colby57  

Ну, раз ты решил докапываться до моей идеи, то и я буду преследовать ту же цель в твоих ответах мне

Бля, мужик..
Если пытаешься меня чему-то учить (будучи зная меньше чем я)
Давай не будем прибегать к оценке чужих знаний. Это как минимум некультурно.

Я тоже мог доебаться до каждой строки кода у тебя, но как ты видишь я этого не сделал.

Цитата:
Сообщение от colby57  

если бы в дебаггере вместо инт3 юзался твой код, бедные реверсеры бы каждый день тебе отписывали с баг-репортом, что контекст их программы каким-то чудом умудрился сломаться...
Я тебе просто указал на неполноценность твоего решения. Это не general-purpose решение. В этом моя основная претензия.

Как минимум сканер сломается если брейкпоинт ставить не на первую инструкцию функции. Ну и хотя бы на ff25 проверку добавил бы.
 
Ответить с цитированием

  #10  
Старый 12.02.2023, 03:54
Ahora57
Новичок
Регистрация: 11.02.2023
Сообщений: 4
С нами: 1713832

Репутация: 13
По умолчанию

Цитата:
Сообщение от kin4stat  

Я тебе просто указал на неполноценность твоего решения. Это не general-purpose решение. В этом моя основная претензия.
Как минимум сканер сломается если брейкпоинт ставить не на первую инструкцию функции. Ну и хотя бы на ff25 проверку добавил бы.
Давай не будем прибегать к оценке чужих знаний -> Много чего не учтено. По хорошему тут чуть ли не эмулятор прикручивать надо.

Тот же long jmp игнорируется(ff 25) -> Ну и хотя бы на ff25 проверку добавил бы.

Простите, но это больше напоминает: "Ты должен добавить, но у меня точно нет претензий и из-за этого я прошу 2 раза добавить проверку на ff 25".

Цитата:
Сообщение от kin4stat  

Или можно просто Ctrl+F8 нажать. Тоже работает.

Думаю вопрос исчерпан.
Я не совсем понимаю, зачем вы показали в одношаговой трассировке обработку INT3 для программы (параметры-> ядро -> пропускать INT3 при пошаговом выполнении). Да, некоторые ошибки можно пропустить (проглотить исключения/пропустить исключения).

Опять же смотрим, как тот же x64dbg обрабатывает это.

Я не хочу смотреть и продолжать этот бессмысленный спор. Давайте его закончим со следующими мыслями:

1)Это просто пример.

Давайте не будем утверждать, что те же некоторые отсталые AV хукают в DLL Api/NtApi или что нужно больше детектов.

Это сделано для новичкови мы не будем говорить 1000 раз НО.

2)Не надо доказывать, что я умнее тебя и продолжать из-за этого спор + при этом докапываться при этом к любому слову.

Как-то Frostiest сказал умную, но простую мысль ~его слова: "Вам не нужно быть гением, чтобы общаться из-за этого с гениями".
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.