Jump to content

Invocar instrucoes assembly no codigo C e escrever sua saida em uma variavel


unc4nny

Recommended Posts

Posted

Oi.
No livro Practical Reverse Engineering, o autor mostra um trecho de codigo asm. Numa parte do codigo, tem a seguinte sequencia de instrucoes:
image.png.c59dc295e45b5a6d7e3c6b352f0dcd67.png

image.png.c4388e794effe18a5bef809d7929ad3f.png

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!
 

  • Fernando Mercês changed the title to Invocar instrucoes assembly no codigo C e escrever sua saida em uma variavel
Posted

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.


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á.

Posted

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!!

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...