Random IRC quote :      <coder> apolitico no es nadie, y en general los que se llaman apoliticos son de derechas <h> coder: yo soy apolitico

Rootkit Arsenal, Installing a Call Gate

Buenas, leyendo el libro “The Rootkit Arsenal: Escape and Evasion in the Dark Corners of the System” quería matizar un par de cosas sobre el capítulo “Hooking the GDT – Installing a Call Gate”. Al final del artículo se incluye un POC driver con el soporte del WalkGDT para varios COREs entre otras.

Una Call Gate es un mecanismo en la arquitectura x86 de Intel para cambiar el nivel de privilegio de la CPU cuando se ejecuta una función predefinida llamada mediante una instrucción CALL/JMP FAR.

Una llamada a una Call Gate permite obtener un privilegio superior al actual, por ejemplo podemos ejecutar con un CALL FAR en ring3 una rutina en ring0. Una Call Gate es una entrada en la GDT (Global Descriptor Table) o en la LDT  (Local Descriptor Table).

Windows no utiliza Call Gates para nada en especial, pero hay malware como el gusano Gurong.A, que instala una Call Gate a través de \Device\PhysicalMemory para ejecutar código en ring0. Un artículo que ya hablaba sobre el tema es “Playing with Windows /dev/(k)mem” de crazylord publicado en la Phrack 59.

Hoy en día no se puede hacer tan fácilmente lo de acceder a /Device/PhysicalMemory, recomiendo leer la presentación de Alex Ionescu  en la RECON 2006 “Subverting Windows 2003 SP1 Kernel Integrity Protection“. También hay ejemplos por la red que usan la API ZwSystemDebugControl para instalar una Call Gate, pero como comenta el artículo de Ionescu tampoco funciona hoy en día (aunque siempre hay técnicas para reactivarlos de nuevo).

IMHO, la mejor manera para instalar una Call Gate es un driver como lo hace el ejemplo del libro Rootkit Arsenal, ahora voy a explicar el ejemplo que trae y añadir algunas cosas que veo que faltan:
Una entrada en la GDT tiene esta pinta:

typedef struct _SEG_DESCRIPTOR
{
WORD size_00_15;
WORD baseAddress_00_15;
WORD baseAddress_16_23:8;
WORD type:4;
WORD sFlag:1;
WORD dpl:2;
WORD pFlag:1;
WORD size_16_19:4;
WORD notUsed:1;
WORD lFlag:1;
WORD DB:1;
WORD gFlag:1;
WORD baseAddress_24_31:8;
} SEG_DESCRIPTOR, *PSEG_DESCRIPTOR;

Y una Call Gate es un tipo de entrada en la GDT con el siguiente aspecto:

typedef struct _CALL_GATE_DESCRIPTOR
{
WORD offset_00_15;
WORD selector;
WORD argCount:5;
WORD zeroes:3;
WORD type:4;
WORD sFlag:1;
WORD dpl:2;
WORD pFlag:1;
WORD offset_16_31;
} CALL_GATE_DESCRIPTOR, *PCALL_GATE_DESCRIPTOR;

offset_00_15: es la parte baja de la dirección de la rutina que se ejecutará en ring0, offset_16_31 es la parte alta.

selector: especifica el segmento de código, con el valor KGDT_R0_CODE (0×8), la rutina se ejecutará con privilegios de ring0.

argCount: es el número de argumentos de la rutina en DWORDs.

type: es el tipo de descriptor, para una Call Gate de 32 bits necesita el valor 0xC

dpl: es el privilegio mínimo que debe tener el código que llama para poder ejecutar la rutina, en te caso 0×3, ya que será llamada por una rutina de ring3.

Los pasos para crear una Call Gate son:

  1. Construir la Call Gate que apunte a nuestra rutina.
  2. Leer el registro GDTR para poder encontrar la GDT usando la instrucción: SGDT. El registro GDTR tiene la siguiente pinta:
    typedef struct _GDTR
    {
    WORD  nBytes;
    DWORD baseAddress;
    } GDTR;

Para obtener el número de entradas en la GDT basta con un GDTR.nBytes / 8.

  1. Buscar una entrada libre en la GDT.
  2. Escribir la Call Gate.

Para llamar a la Call Gate solo es necesario hacer un CALL FAR al selector de la GDT, es decir si hemos introducido la Call Gate en la entrada 6 de la GDT, la aplicación de espacio de usuario deberá ejecutar un CALL FAR 006:00000000. La otra parte del FAR CALL no sirve para nada pero debe estar en la instrucción.

La rutina de la Call Gate debe salvar los registros: EAX, ECX, EDX, EBX, EBP, ESP, ESI, EDI, EFLAGS y FS. Además debe desactivar las interrupciones con CLI. El selector de FS debe ser 0×30, después solo es necesario restaurar los registros y activar las interrupciones con STI y un RETF si se desea volver a ring3. Todo esto está sacado de nt!KiDebugService() por si te lo estás preguntando.

Bueno y ahora es el momento de los matices, el POC code del libro no tiene en cuenta la posibilidad de existir varios COREs, esto quiere decir que solo es capaz de instalar la Call Gate en el CORE que toque cuando se cargue el driver y la GDT del otro CORE queda intacta, el problema es que si la aplicación de espacio de usuario hace un FAR CALL estando en otro CORE donde no existe la Call Gate no funcionará.

En Windows es sencillo controlar esto con dos APIs: para obtener el número de COREs se puede usar un simple

GetSystemInfo:
void WINAPI GetSystemInfo(
__out  LPSYSTEM_INFO lpSystemInfo
);

Para el número de COREs lógico se puede usar GetLogicalProcessorInformation.
SYSTEM_INFO tiene la siguiente pinta:

typedef struct _SYSTEM_INFO {

DWORD     dwNumberOfProcessors;

}SYSTEM_INFO;

Con el campo dwNumberOfProcessors podemos realizar un bucle para ir CORE por CORE añadiendo la Call Gate, también se puede forzar al driver a instalar la Call Gate en el primer core (1) y que la aplicación de espacio de usuario solo se ejecute en el core 1, esto se consigue con la API: SetThreadAffinityMask, que es asín:

DWORD_PTR WINAPI SetThreadAffinityMask(
__in  HANDLE hThread,
__in  DWORD_PTR dwThreadAffinityMask
);

Pasándole un GetCurrentThread() y como AffinityMask el valor 1,

Affinity = 1;
SetThreadAffinityMask( GetCurrentThread(), Affinity );

Ojito, DWORD_PTR no es un puntero a DWORD, se pasa por valor.

Si se hace un for con el número de procesadores y con la variable índice (el primero core es 1 no 0) como Affinity puedes instalar una Call Gate en todos los cores.

En el driver que adjunto como POC desde el driver muestro la GDT de todos los COREs para mostrar lo que digo, solo saldrá la Call Gate en un CORE.

Para hacer esto desde un driver es necesario un:

ZwQuerySystemInformation( SystemBasicInformation, &amp; system_basic_information, sizeof( system_basic_information ), NULL );

Para obtener el número de cores y un:

ZwSetInformationThread( (HANDLE) -2, ThreadAffinityMask, &amp; AffinityMask, sizeof( AffinityMask ) );

Para cambiar de core, -2 es el equivalente del GetCurrent…

Otra cosa rara del POC del libro es que pasaba la GDT por valor y no el puntero a PrintGDT y eso me daba problemas, lo he cambiado para que se pase como PSEG_DESCRIPTOR y todo funciona sin problemas.

Y esto es todo, el código es bastante claro, espero que se haya entendido, un saludo desde 48bits.

Descargar el driver desde aquí: http://www.48bits.com/files/cgaty.rar

Driver probado en: XP y VISTA (bin driver: WinDDK 6001.17121 & XP x86 Free build).

Algunas lecturas sobre call gates:

http://www.phrack.com/issues.html?issue=59&id=16

http://en.wikipedia.org/wiki/Call_gate

http://www.intel.com/design/processor/manuals/253668.pdf
http://ricardonarvaja.info/WEB/OTROS/TUTES%20SACCOPHARYNX/
http://members.fortunecity.com/blackfenix/callgates.html

43 Comentarios para “Rootkit Arsenal, Installing a Call Gate” »»

  1. Comentario por pluf | 01/08/10 at 8:57 am

    guapo!! :)

  2. Comentario por mikelet | 01/08/10 at 10:29 am

    Que aria io sin bosotros!!

  3. Comentario por Ruben | 01/08/10 at 11:10 am

    Primer post también de David, que ya tiene tablas en esto. Hemos empezado el año con mucha actividad, mola. Creo que va a estar interesante el 2010.
    Muy bien explicado!

  4. Comentario por plusvic | 01/08/10 at 12:23 pm

    Guapo, guapo. Menuda racha que lleva el blog.

  5. jon
    Comentario por jon | 01/08/10 at 3:52 pm

    Gran trabajo david! ;) Hoy día es fundamental pensar en mas de un core al programar cualquier cosa. Me extraña que al autor se le haya escapado este tema por que el PoC del resto de capitulos recuerdo que cuidaba el tema. A ver si en el futuro podemos aportar más sobre el tema de rootkits que no parece haber mucho movimiento!

  6. Comentario por kktmp1 | 01/08/10 at 4:49 pm

    Buen aporte Dreg.. muchas gracias. Ya veo que esta todo dios leyendo el libro de Blunden. Realmente es muy bueno. Estoy deseando ver con que nos sorprente a primeros de Febrero en el BH DC2010. “An Uninvited Guest (Who Won’t Go Home)”… promete.

    Sobre rootkits.. al loro también a la evolucion del Stoned Bootkit. Un RK que se instala en el MBR y que ya es capaz de leer ficheros en Raw sobre espacio no particionado o sectores marcados como defectuosos… esta misma semana Peter ha publicado la version 2.

  7. Comentario por David Reguera | 01/08/10 at 6:02 pm

    Gracias chicos, he mandado un mail a Blunden por si hacen alguna revisión o algo así que puedan actualizarlo.

  8. Comentario por LocoDelAssembly | 01/08/10 at 7:19 pm

    Hola, me parece que esta línea está mal:
    AffinityMask = j + 1;

    Debería ser esta:
    AffinityMask = 1 << j;

    Sino, en la primera iteración se activa el primer procesador lógico, en la segunda iteración se activaría el segundo (perfecto para Core2 Duo hasta acá :P ), en la tercera ya se activarían el primero y el segundo al mismo tiempo.

    Ya que he escrito aprovecho para dar infinitas gracias por este blog, siempre excelente!

  9. Comentario por David Reguera | 01/08/10 at 10:29 pm

    Bueno esto era a modo de ejemplo, solo vale para dos COREs, en breve estará subido el driver con el AffinityMask = 1 << j; en el src y el .sys, el paper en inglés y además un comentario hablando sobre lo de como manejar la máscara.

  10. Comentario por Juan C. Montes | 01/12/10 at 8:22 am

    Buen texto David, :)

    Pero para que usar un driver para meter una callgate… cuando ya estas en ring0?

  11. Comentario por David Reguera | 01/12/10 at 10:03 am

    Bueno, quizá por que luego tengas un APP de userspace que tire del callgate para quien depure la app le cueste más o por que es un friki, yo que se xD.

    Pero vamos, la idea de enseñar el tema de las Call Gates desde un driver en ring0 es útil por que el código siempre funciona y no hay que andar con lo de habilitar el pysical o la api de debug que ya no funciona directamente.

    No obstante la intención del POST era simplemente matizar el tema de los call gates siguiendo el ejemplo de rootkit arsenal, que no metía lo del affinity y cosas así.

    Un saludo.

  12. Comentario por Alon | 01/18/10 at 4:47 am

    Muy bueno el post!!! Enhorabuena tb x tu trabajo en el RKU.

    Un saludo

  13. Comentario por SparK | 02/07/10 at 2:35 am

    Buen post david!

    Interesante la técnica y teniendo en cuenta varios cores.

    Un abrazo.

  14. Comentario por David Reguera | 02/19/10 at 5:19 pm

    Aclaración sobre lo del selector y el CALL FAR 6,

    En la GDT el selector 0×320, sería en binario 1100100000 = Entry:1100100(GDT) TI=0 RPL=00.

    Así pues es necesario un CALL FAR 0×320 para ejecutar una Call Gate en la GDT (TI = 0) en la entrada 100 (1100100) y el RPL 00.

  15. Comentario por mybook | 03/16/10 at 4:37 am

    The darkmoon fair comes to Mulgore or Elwyn forest once a month. There are no guards so it is possible to attend the other wow power leveling factions fair. wow power leveling THe muglore 1 is forest fair is next to Goldshire.
    The fair comes with many fun and exciting options. You can exchange items for tickets which you can buy thigns with. You world of warcraft gold can use a massive cannon which fires you into the air a long way. potent ale very cheaply. And last but not 重庆二手交易 least you can giveto combine into an epic trinket.
    The Epic gold in wow Neck:
    A good gear could mean Victory wow gold eu or Death when you fight someone or something (PvP, PvE, Grind, Instances).
    For wow gold cheap a “little” favor or whit a little work you can have an Epic Trinket!
    The “Male” wow cheap gold classes could profit mostly (DD Warrior, DD Paladin, Rogues or Hunters too) from the First one:

  16. Comentario por new york divorce lawyer | 01/23/11 at 7:50 am

    The tutorial is very simple and explained to a great level. It doesn’t take any effort from our side to grasp it! I guess now I understand what the threshold function was for and how it could be used to make striking line art conversion effects!

  17. Comentario por musica de relajacion | 01/23/11 at 3:59 pm

    Very useful tutorial. Much appreciated. Thanks

  18. Comentario por pajama jeans | 01/23/11 at 5:35 pm

    Just wanted to drop a comment and say I am new to your blog and really like what I am reading. Thanks for the great content. Look forward to coming back for more.

  19. Comentario por Buy Used College Books | 01/24/11 at 3:15 pm

    I want to take this moment to say that I really love this blog. It has been a good resource of information for me. Thank you so much

  20. Comentario por How To Get Rid of Bedbugs | 01/24/11 at 5:53 pm

    Looks like you are a specialist on this because you just made it so easy to be with you, motivated me to learn more on the subject! May I ask you, do you devote a lot of effort to it because you seem to be so in tune with

  21. Comentario por nyc therapists | 01/26/11 at 9:29 am

    I am very enjoyed for this blog. Its an informative topic. It help me very much to solve some problems. Its opportunity are so fantastic and working style so speedy. I think it may be help all of you. Thanks a lot for enjoying this beauty blog with me. I am appreciating it very much! Looking forward to another great blog. Good luck to the author! all the best!

  22. Comentario por Private Leasing Deals | 03/01/11 at 10:41 am

    Para obtener el número de entradas en la GDT basta con un GDTR.nBytes / 8.

  23. Comentario por Gold Market | 03/04/11 at 8:44 am

    The fair comes with many fun and exciting options. You can exchange items for tickets which you can buy thigns with.

  24. Comentario por Buy Halloween Adults Costumes | 03/04/11 at 10:15 am

    I ask you, do you devote a lot of effort to it because you seem to be so in tune with

  25. Comentario por blank sudoku | 03/15/11 at 8:47 am

    yes I love a good tutorial, as well, always a benefit, thanks

  26. Comentario por Conspiracy Theories | 03/15/11 at 2:47 pm

    Thanks very much. I found the tutorial very useful so kudos to you and a big thumbs up from me

  27. Comentario por 2012 world ending | 03/17/11 at 1:05 pm

    Thanks for this excellent post. Very Illuminating and thought provoking. I will certainly be taking on board all these thought proving comments. Great blog and thanks again.

  28. Comentario por real jobs at home | 03/18/11 at 3:27 pm

    A very interesting and enlightening blog..Thanks for all the insightful posts..really got me thinking..Kudos

  29. Comentario por Car Leasing Deals | 04/18/11 at 12:13 pm

    It is a very informative and useful post thank it is good material to read this post increases may knowledge.

  30. Comentario por haibo | 04/27/11 at 4:34 am

    Thanks so much. The tutorial is really helpful and easy to follow.

  31. Comentario por Jordans | 05/09/11 at 10:01 am

    Fantastic beat ! I wish to apprentice at the same time as you amend your website, how can i subscribe for a weblog site? The account helped me a acceptable deal. I

    were tiny bit acquainted of this your broadcast offered bright transparent idea

  32. Comentario por Survival PDF | 05/11/11 at 5:44 pm

    Kudos to you. Great blog and I found it very informative, Thanks a lot

  33. Comentario por Survival PDF | 05/11/11 at 5:46 pm

    Fantastic information and I found it very useful so thanks for the great blog!!

  34. Comentario por Residential cleaning in Madison | 05/12/11 at 1:34 pm

    Thanks for posting such a nice article

  35. Comentario por Horyzont | 05/13/11 at 2:54 pm

    well, thanks a lot for giving me the opportunity to contribute, I really appreciate that!

  36. Comentario por laptop backpacks | 05/28/11 at 12:06 am

    Thanks for teaching me how to install this, I was looking for a guide on how to do this actually.

  37. Comentario por john | 06/06/11 at 5:36 am

    great call gate discussion. thanks!

  38. Comentario por medical coding and billing | 06/14/11 at 10:59 am

    My Sql seems to becoming more used application every day. I don’t quite follow it as yet.

  39. Comentario por Damenschuh | 06/14/11 at 3:30 pm

    MySQl, i remember to create new profiles every time I create a new website, and place it in a proper hosting. it is essential

  40. Comentario por Ryan | 06/19/11 at 5:45 am

    Hello, you have made some excellent points here, many thanks for sharing this great content! I hope that you can manage to keep this great work flowing. All the best.

  41. Comentario por snowboots | 06/19/11 at 5:47 am

    Good evening friend! Many thanks for sharing this great post! Much can be learnt at this valuable resource. Keep up the great work.:)

  42. Comentario por mlb jerseys cheap | 06/28/11 at 10:54 am

    1. Great article! thanks for sharing!

  43. Comentario por termite treatment cost | 06/30/11 at 8:55 am

    Fantastic information and I found it very useful so thanks for the great blog!!

Dejar un comentario »»