View Full Version : tracer or Writing tracer without using Windows Debug API

January 31st, 2011, 17:50
This time I decided to publish source code of an driver which I used for stealth debugging and tracing protections. I've successfully used it with many packers/protectors but most important projects which I made, and which were using this are themida and aspr 2.3 ske unpackers. Now whole code for this small tracing driver is available at : http://deroko.phearless.org/engines.html

January 31st, 2011, 18:39
Can be use the exception port(by theory).

February 1st, 2011, 02:29
good idea, would be nice to check and see how it works in nutshell, and if it can be used

February 1st, 2011, 11:28
At the beginning of the exception is delivered to the debug port, then exception port(in KiDispatchException()).
IN BOOLEAN DebugException,
IN BOOLEAN SecondChance


Routine Description:

This function is called forward an exception to the calling process's
debug or subsystem exception port.


ExceptionRecord - Supplies a pointer to an exception record.

DebugException - Supplies a boolean variable that specifies whether
this exception is to be forwarded to the process's
DebugPort(TRUE), or to its ExceptionPort(FALSE).

Return Value:

TRUE - The process has a DebugPort or an ExceptionPort, and the reply
received from the port indicated that the exception was handled.

FALSE - The process either does not have a DebugPort or
ExceptionPort, or the process has a port, but the reply received
from the port indicated that the exception was not handled.




args = &m.u.Exception;

// Initialize the debug LPC message with default information.


// Get the address of the destination LPC port.

Process = PsGetCurrentProcess();
if (DebugException) {
if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) {
Port = NULL;
} else {
Port = Process->DebugPort;
LpcPort = FALSE;
} else {
Port = Process->ExceptionPort;
m.h.u2.ZeroInit = LPC_EXCEPTION;
LpcPort = TRUE;

// If the destination LPC port address is NULL, then return FALSE.

if (Port == NULL) {
return FALSE;

// Fill in the remainder of the debug LPC message.

args->ExceptionRecord = *ExceptionRecord;
args->FirstChance = !SecondChance;

// Send the debug message to the destination LPC port.

if (LpcPort) {
st = DbgkpSendApiMessageLpc(&m,Port,DebugException);
} else {
st = DbgkpSendApiMessage(&m,DebugException);

// If the send was not successful, then return a FALSE indicating that
// the port did not handle the exception. Otherwise, if the debug port
// is specified, then look at the return status in the message.

if (!NT_SUCCESS(st) ||
((DebugException) &&
(m.ReturnedStatus == DBG_EXCEPTION_NOT_HANDLED || !NT_SUCCESS(m.ReturnedStatus)))) {
return FALSE;

} else {
return TRUE;

This type of lpc-messages LPC_EXCEPTION. Port handle can be passed to NtCreateProcess. Maybe one time set using NtSetInformationProcess(class:ProcessExceptionPort). The port is set in the notification csrss(\ApiPort):
/* Set the Exception port to us */
Status = NtSetInformationProcess(hProcess, ProcessExceptionPort, &CsrApiPort, sizeof(HANDLE));

http://doxygen.reactos.org/db/da3/subsystems_2csr_2csrsrv_2api_8c_source.html ("http://doxygen.reactos.org/db/da3/subsystems_2csr_2csrsrv_2api_8c_source.html")
http://doxygen.reactos.org/d1/d3c/subsystems_2csr_2csrsrv_2process_8c_source.html ("http://doxygen.reactos.org/d1/d3c/subsystems_2csr_2csrsrv_2process_8c_source.html")
Processing messages in CsrApiRequestThread() ^.

February 1st, 2011, 15:30
so it's already documented

February 12th, 2011, 04:17
Yes, but it does not matter. Exception port can not be easy to set:
Отладка посредством порта ислючений.
o При создании процесса выполняется нотификация csrss, поток(CsrApiRequestThread()) обрабатывающий запро
сы с сервисного порта(\ApiPort) вызывает CsrCreateProcess(), в этой функции помимо иной работы устанав
ливается порт ислючений(ProcessExceptionPort). Установка порта может быть выполнена однократно, если у
становить порт передав его описатель в NtCreateProcess, то предыдущая функция вернёт STATUS_PORT_ALREA
DY_SET, сервер возвратит STATUS_NO_MEMORY. Далее CreateProcess() завершится с ошибкой. Если не выполня
ть нотификацию, то при инициализации процесса при подключении к серверу из процедуры инициализации Ker
nel32(в CsrpConnectToServer() -> NtSecureConnectPort) будет возвращена ошибка(CsrApiHandleConnectionRe
quest() не найдёт описатель потока в базе, который добавляется туда при инициализации и сервер отклони
т запрос на соединение возвратив STATUS_PORT_CONNECTION_REFUSED), загрузчик выведет сообщение и сгенер
ирует исключение.
o Не целевые(LPC_EXCEPTION) сообщения следует передавать на сервер.
Эти проблемы решаются захватом CsrApiRequestThread(). Это решит предыдущие проблемы и позволит выполнять
глобальную обработку сообщений. Управлять надстройкой можно также через сервисный порт.

The implementation should not be a problem.

February 12th, 2011, 04:32
However, it's not extremely helpful to post Russian language instructions/comments for a mostly English Forum.


February 12th, 2011, 08:49
Heh true true, but for the people out 'there' interested in such.. the 'looking' at obfuscation as a 'common obstacle' even for 'protections' this is a common place, in non english speaking countries..I answer in english..xD

why do you 'think' I place 'logical' hard to follow errors in my code...? I for 1 am willing to translate and dig...IE if I'm lazy to just paste it into a translator, I search for elements that should be relevant across languages..Api names, author cross references, API call constants..so forth.

I guess I really didn't have a point..so..In the interest 'community' I got it..


Debugging through the port islyucheny.
o When you create a notification process is performed csrss, stream (CsrApiRequestThread ()) handle the forbidden
raw from the service port (\ ApiPort) is CsrCreateProcess (), this function in addition to other work establishes
logger port islyucheny (ProcessExceptionPort). Port setting can be done once, if
becoming the port gave its descriptor NtCreateProcess, then the previous function returns STATUS_PORT_ALREA
DY_SET, the server will return STATUS_NO_MEMORY. Next CreateProcess () fails. If you do not
Th notification, then the initialization process when connecting to the server from an initialization procedure, Ker
nel32 (in CsrpConnectToServer () -> NtSecureConnectPort) will return an error (CsrApiHandleConnectionRe
quest () will not handle the flow in the database, which is added back during the initialization and the server rejected
m connection request returning STATUS_PORT_CONNECTION_REFUSED), the loader will print a message and Generate
iruet exception.
o Do not trust (LPC_EXCEPTION) messages should be transmitted to the server.
These problems are solved capture CsrApiRequestThread (). This will solve the previous problems and will allow
global processing of messages. You can also add and manage through the service port.

Also a rebuttal to 'The exception port is not so easily set'...NtSystemDebugControl from userland couldn't do it?

February 12th, 2011, 11:43
There is no need to translate what was said. Have you found more russian than you think

Also a rebuttal to 'The exception port is not so easily set'...NtSystemDebugControl from userland couldn't do it?

You have translated the description of the reasons