Bij gebrek aan een code base maar in 'n topic hier
Na vorige week wat mensen creatief bezig zien zijn met het inserten van code in andere processen dmv de debug api en hooks ben ik zelf ook maar es gaan kijken wat je nog meer voor leuke dingen met die debug api kon doen
Goed dan zit je van "ja je wilt er wat mee doen maar wat!? " (Ik denk dat de meeste dit gevoel wel kennen. Gelukkig was ik net hersendood genoeg om onder NT de win95 versie van lcdinf op te starten welke mij op een mooie error trakteerde: "Privileged instruction" Ah okay dan slachtoffer gevonden! Maarja nu rest de vraag wat voor instructie wil ie doen?!
Goed we starten onze trouwe WinDbg op. Laden lcdinf en geven 'n ram op de run knop. Waarna al snel een "Unknown exception - code c0000096 (first chance)" verschijnt, maar de debugger breaked er niet op , niet zo handig,we laden het process opnieuw maar nu gaan we bij Debug->Event filters maar es een eventje toevoegen. Event code c0000096 en de rest lekker laten wat het is. we geven de run knop opnieuw een trap. Waarna WinDbg de volgende informatie presenteerd..
Tjah Dat zat er dik in, directe hardware IO dat vind NT niet zo prettig, maar als WinDbg dit kan afvangen is dit ook vast wel mogelijk met eigen software.
Na even wat gezocht te hebben in MSDN kwam ik op deze pagina terrecht welke mij dit
Goed ons process loopt , wat nu?! Wachten op debug events natuurlijk! En dat doen we met WaitForDebugEvent, Goed we hebben ons event binnen en dan verwachten ze natuurlijk dat we er wat mee doen waarna we even melden wat de vervolg acties moeten worden. Wat we doen met ContinueDebugEvent.
Implementatie is wederom niet zo heel erg ingewikkeld.
Goed het process loopt en we krijgen schijnbaar onze debug events binnen, nou dan die nasty 0xc0000096 error maar es nailen. We wachten tot we een EXCEPTION_DEBUG_EVENT krijgen, Controleren dat het een 0xc0000096 exception is. Maar omdat we alleen die out dx,al (opcode 0xEE had WinDbg ons verteld) willen afvangen gaan we eens rondneuzen op het adres waar de Exception optrad dmv ReadProcessMemory vinden we daar 0xEE dan is ie voor ons, en anders gooien we 'm terug en laten we windows het zelf maar uit zoeken.
Goed we hebben onze exception ,we weten dat ze direct de hardware benaderen maar nu willen we nog weten wat de waardes van de registers waren op dat moment, zodat we de hardware io af kunnen handelen door DlPortio , het ophalen van de register waardes doen we met GetThreadContext, We vissen EAX & EDX er uit en laten DLportio de hardware io voor ons uitvoeren. Vervolgens zetten we de Instructie pointer (EIP) eentje verder want onze "out dx,al" is inmiddels afgehandeld. waarna dmv SetThreadContext de Registerwaardes terug het process in schrijven. waarna het process z'n gangete weerverder gaat.
Goed we debuggen een process, handlen wat excepions af klinkt allemaal leuk en aardig, maar werkt het ook? Ja het werkt, maar door dat we instrucie vervangen die normaal gesproken maar een paar klok tikken duurt met onze eigen code *VEEL* meer kloktikjes zuipt is de performance uiteraard ver te zoeken, maar performance was het doel ook helemaal niet , hoet doel was uitzoeken of je een win95 applicatie die directe hardware io doet, zonder modificaties aan de praat krijgt op een NT based systeem en dat is gelukt.
De sourcecode in dit topic is hier en daar een beetje uit context getrokken en ik heb ook wat minder belangrijke details weggelaten, klik hier voor een zipje met de source.
Na vorige week wat mensen creatief bezig zien zijn met het inserten van code in andere processen dmv de debug api en hooks ben ik zelf ook maar es gaan kijken wat je nog meer voor leuke dingen met die debug api kon doen
Goed dan zit je van "ja je wilt er wat mee doen maar wat!? " (Ik denk dat de meeste dit gevoel wel kennen. Gelukkig was ik net hersendood genoeg om onder NT de win95 versie van lcdinf op te starten welke mij op een mooie error trakteerde: "Privileged instruction" Ah okay dan slachtoffer gevonden! Maarja nu rest de vraag wat voor instructie wil ie doen?!
Goed we starten onze trouwe WinDbg op. Laden lcdinf en geven 'n ram op de run knop. Waarna al snel een "Unknown exception - code c0000096 (first chance)" verschijnt, maar de debugger breaked er niet op , niet zo handig,we laden het process opnieuw maar nu gaan we bij Debug->Event filters maar es een eventje toevoegen. Event code c0000096 en de rest lekker laten wat het is. we geven de run knop opnieuw een trap. Waarna WinDbg de volgende informatie presenteerd..
code:
1
2
3
4
5
6
| Unknown exception - code c0000096 (first chance) eax=00000130 ebx=7ffe030a ecx=0012fdac edx=00000378 esi=00442840 edi=008c1918 eip=0043fbaa esp=0012f9dc ebp=0012fe20 iopl=0 nv up ei pl nz na po cy cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010207 image00400000+3fbaa: 0043fbaa ee out dx,al |
Tjah Dat zat er dik in, directe hardware IO dat vind NT niet zo prettig, maar als WinDbg dit kan afvangen is dit ook vast wel mogelijk met eigen software.
Na even wat gezocht te hebben in MSDN kwam ik op deze pagina terrecht welke mij dit
Wist te melden, okay.. simpel genoeg. Implementatie spreekt voor zich eigenlijk voor meer info moet je even kijken in de documentatie van CreateProcessThe CreateProcess function enables a debugger to start a process and debug it. The fdwCreate parameter of CreateProcess is used to specify the type of debugging operation. If the DEBUG_PROCESS flag is specified for the parameter, a debugger debugs the new process and all of the process's descendants, provided that the descendants are created without the DEBUG_PROCESS flag.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( !CreateProcess( NULL, // No module name (use command line).
"c:\\lcdinf\\lcdinf95.exe", // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
DEBUG_PROCESS, // Debug it!!
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
OutputDebugString( "CreateProcess failed." );
return 0;
}
printf("Debugging process %.8x\n",pi.dwProcessId); |
Goed ons process loopt , wat nu?! Wachten op debug events natuurlijk! En dat doen we met WaitForDebugEvent, Goed we hebben ons event binnen en dan verwachten ze natuurlijk dat we er wat mee doen waarna we even melden wat de vervolg acties moeten worden. Wat we doen met ContinueDebugEvent.
Implementatie is wederom niet zo heel erg ingewikkeld.
code:
1
2
3
4
5
6
7
8
9
| DEBUG_EVENT DebugEv; // debugging event information
for(;;) //Until hell freezes over
{
DWORD dwContinueStatus = DBG_CONTINUE ;
WaitForDebugEvent(&DebugEv, INFINITE);
ContinueDebugEvent(DebugEv.dwProcessId,
DebugEv.dwThreadId, dwContinueStatus);
} |
Goed het process loopt en we krijgen schijnbaar onze debug events binnen, nou dan die nasty 0xc0000096 error maar es nailen. We wachten tot we een EXCEPTION_DEBUG_EVENT krijgen, Controleren dat het een 0xc0000096 exception is. Maar omdat we alleen die out dx,al (opcode 0xEE had WinDbg ons verteld) willen afvangen gaan we eens rondneuzen op het adres waar de Exception optrad dmv ReadProcessMemory vinden we daar 0xEE dan is ie voor ons, en anders gooien we 'm terug en laten we windows het zelf maar uit zoeken.
code:
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
| [...]
WaitForDebugEvent(&DebugEv, INFINITE);
switch (DebugEv.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode)
{
case 0xc0000096: //illegal instruction
unsigned char buf;
DWORD BR;
ReadProcessMemory(pi.hProcess,
DebugEv.u.Exception.ExceptionRecord.ExceptionAddress,
&buf,1,&BR);
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED ;
if (buf==0xEE && BR==1) //out dx,al?
{
[...]
}
else //geen out of readmemory probs?
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED ;
break;
}
break;
}
[..] |
Goed we hebben onze exception ,we weten dat ze direct de hardware benaderen maar nu willen we nog weten wat de waardes van de registers waren op dat moment, zodat we de hardware io af kunnen handelen door DlPortio , het ophalen van de register waardes doen we met GetThreadContext, We vissen EAX & EDX er uit en laten DLportio de hardware io voor ons uitvoeren. Vervolgens zetten we de Instructie pointer (EIP) eentje verder want onze "out dx,al" is inmiddels afgehandeld. waarna dmv SetThreadContext de Registerwaardes terug het process in schrijven. waarna het process z'n gangete weerverder gaat.
code:
1
2
3
4
5
6
7
8
9
10
| if (buf==0xEE && BR==1) //out dx,al?
{
CT.ContextFlags = CONTEXT_FULL;
GetThreadContext(hThread,&CT);
printf("%x,%x\n",CT.Edx & 0xffff,(UCHAR)CT.Eax & 0xff);
DlPortWritePortUchar(CT.Edx & 0xffff,(UCHAR)CT.Eax & 0xff);
CT.Eip++; //skip instruction
SetThreadContext(hThread,&CT);
dwContinueStatus = DBG_CONTINUE;
} |
Goed we debuggen een process, handlen wat excepions af klinkt allemaal leuk en aardig, maar werkt het ook? Ja het werkt, maar door dat we instrucie vervangen die normaal gesproken maar een paar klok tikken duurt met onze eigen code *VEEL* meer kloktikjes zuipt is de performance uiteraard ver te zoeken, maar performance was het doel ook helemaal niet , hoet doel was uitzoeken of je een win95 applicatie die directe hardware io doet, zonder modificaties aan de praat krijgt op een NT based systeem en dat is gelukt.
De sourcecode in dit topic is hier en daar een beetje uit context getrokken en ik heb ook wat minder belangrijke details weggelaten, klik hier voor een zipje met de source.