unc4nny Posted April 15, 2020 Posted April 15, 2020 Oi. No livro Practical Reverse Engineering, o autor mostra um trecho de codigo asm. Numa parte do codigo, tem a seguinte sequencia de instrucoes: Pesquisando eu vi que o sidt eh uma instrucao que carrega o Interrupt Descriptor Table no endereco especificado, e ele esta comparando para ver se o base address do IDT esta no range especificado no codigo (8003f400h-80047400h). Isso eh uma tecnica para ver se o programa esta rodando em maquina virtual. A duvida vem aqui: Na hora que o cara vai explicar (decompilar o codigo) ele faz da seguinte maneira: typedef struct _IDTR { DWORD base; SHORT limit; } IDTR, *PIDTR; BOOL __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){ IDTR idtr; __sidt(&idtr); if (idtr.base > 0x08003f40 && idtr.base < 0x80047400) return FALSE; } Minha duvida eh justamente no __sidt(&idtr); Fui tentar reproduzir um codigo similar aqui na minha VM, mas da erro de compilacao. Estou usando o Dev-C++ Segue o codigo: #include <windows.h> #include <stdio.h> typedef struct _IDTR{ DWORD base; SHORT limit; } IDTR, *PIDTR; int main(){ IDTR idtr; __sidt(&idtr); printf( "Base: %d\r\nLimit: %d\r\n", idtr.base, idtr.limit ); return 0; } O erro sendo gerado eh: undefined reference to __sidt. To lendo a documentacao do __asm no site da microsoft mas ate agora nao achei nada que me ajudou. Alguem pode me dar uma luz? Eu quero escrever o Interrupt Descriptor Table em alguma variavel que eu consiga ler, ou ate mesmo ler o IDTR em si. Obrigado desde ja! EDIT: Eu esqueci de escrever o #include <intrin.h> que supostamente eh o headerfile onde __sidt esta definido, mas esta incluso!
Felipe.Silva Posted April 16, 2020 Posted April 16, 2020 Colega, pelo que pesquisei aqui isto é uma instrução intrísseca do compilador do Visual Studio (Microsoft). Tem muita coisa em C que não é padronização da linguagem mas sim de alguma implementação específica, esta é uma delas. https://docs.microsoft.com/pt-br/cpp/intrinsics/sidt?view=vs-2019 Se você usa o GCC, e suponho que sim, você pode usar Inline Assembly para isso. (outros compiladores também suportam Inline Assembly, mas com sintaxe diferente) Vou deixar um exemplo: #include <stdio.h> #include <inttypes.h> typedef struct idtr_s { void *base; uint16_t limit; } idtr_t; inline void sidt(idtr_t *idtr) { __asm__ ( "sidt %0" : "=m" (idtr) ); } int main(void) { idtr_t idt; sidt(&idt); printf("%p, %" PRIu16 "\n", idt.base, idt.limit); return 0; } Detalhe que o uso de uma inline function demanda que você ligue a otimização de código na hora de compilar. Tu pode por exemplo fazer assim: $ gcc -O2 tst.c -o tst Ah, uma pequena nota, sem querer atropelhar o autor. Mas o uso de DWORD para 'base' não está tecnicamente correto. Ele está assumindo que o tamanho do dado será necessariamente 4 bytes, mas isso só é verdade se o programa não estiver rodando em modo de 64-bit. Por isso usei um ponteiro void no lugar. EDIT: A instrução SIDT não carrega a IDT, carrega o IDTR que é um registrador que armazena estas informações sobre a IDT. "base" no caso é o endereço inicial de onde a IDT está.
unc4nny Posted April 16, 2020 Author Posted April 16, 2020 Cara, muito obrigado mil vezes!!! Depois que eu enviei a pergunta eu achei esse inline assembly e nao tava conseguindo fazer funcionar nem a pau. 8 hours ago, Felipe.Silva said: A instrução SIDT não carrega a IDT, carrega o IDTR que é um registrador que armazena estas informações sobre a IDT. "base" no caso é o endereço inicial de onde a IDT está. Ops, eh vdd, my bad. Cara mto obrigado!!
Recommended Posts
Archived
This topic is now archived and is closed to further replies.