Advertisement
Guest User

osi win xp modif

a guest
Dec 21st, 2015
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.46 KB | None | 0 0
  1. /* PANDABEGINCOMMENT
  2.  *
  3.  * Authors:
  4.  *  Tim Leek               tleek@ll.mit.edu
  5.  *  Ryan Whelan            rwhelan@ll.mit.edu
  6.  *  Joshua Hodosh          josh.hodosh@ll.mit.edu
  7.  *  Michael Zhivich        mzhivich@ll.mit.edu
  8.  *  Brendan Dolan-Gavitt   brendandg@gatech.edu
  9.  *  Evan Downing           edowning3@gatech.edu
  10.  *
  11.  * This work is licensed under the terms of the GNU GPL, version 2.
  12.  * See the COPYING file in the top-level directory.
  13.  *
  14. PANDAENDCOMMENT */
  15. #define __STDC_FORMAT_MACROS
  16.  
  17. typedef unsigned char BYTE;
  18.  
  19. #include <distorm.h>
  20. namespace distorm {
  21. #include <mnemonics.h>
  22. }
  23.  
  24. extern "C" {
  25.  
  26. #include "config.h"
  27. #include "qemu-common.h"
  28. #include "cpu.h"
  29.  
  30. #include "panda_plugin.h"
  31. #include "panda_plugin_plugin.h"
  32. #include "../osi/osi_types.h"
  33. #include "../osi/os_intro.h"
  34.  
  35.  
  36. bool translate_callback(CPUState *env, target_ulong pc);
  37. int exec_callback(CPUState *env, target_ulong pc);
  38. #ifdef TARGET_I386
  39. bool init_plugin(void *);
  40. void uninit_plugin(void *);
  41. void on_get_current_process(CPUState *env, OsiProc **out_p);
  42. void on_get_processes(CPUState *env, OsiProcs **out_ps);
  43. void on_get_libraries(CPUState *env, OsiProc *p, OsiModules **out_ms);
  44. void on_free_osiproc(OsiProc *p);
  45. void on_free_osiprocs(OsiProcs *ps);
  46. void on_free_osimodules(OsiModules *ms);
  47. #endif
  48. FILE *plugin_log;
  49. }
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53.  
  54. #include <iostream>
  55. #include <iomanip>
  56. #include <sstream>
  57.  
  58. #include <cstring>
  59. #include <string>
  60.  
  61.  
  62. #ifdef TARGET_I386
  63.  
  64. // Code should work for other versions of Windows once these constants
  65. // are redefined. Possibly we should move them to a config file?
  66.  
  67. #define KMODE_FS           0x030 // Segment number of FS in kernel mode
  68. #define KPCR_CURTHREAD_OFF 0x124 // _KPCR.PrcbData.CurrentThread
  69. /*
  70.   NOTE - KTHREAD_KPROC should be _KTHREAD.Process, but this does not exist in
  71.          Windows XP SP3 like it does in Windows 7.
  72.          _ETHREAD.ThreadsProcess should work just fine
  73. */
  74. #define KTHREAD_KPROC_OFF  0x220 // _ETHREAD.ThreadsProcess
  75. #define EPROC_TYPE_OFF     0x000 // _EPROCESS.Pcb.Header.Type
  76. #define EPROC_SIZE_OFF     0x002 // _EPROCESS.Pcb.Header.Size
  77. #define EPROC_TYPE          0x03 // Value of Type
  78. #define EPROC_SIZE          0x1b // Value of Size
  79. #define EPROC_DTB_OFF      0x018 // _EPROCESS.Pcb.DirectoryTableBase
  80. #define EPROC_PID_OFF      0x084 // _EPROCESS.UniqueProcessId
  81. #define EPROC_LINKS_OFF    0x088 // _EPROCESS.ActiveProcessLinks
  82. #define EPROC_PPID_OFF     0x14c // _EPROCESS.InheritedFromUniqueProcessId
  83. #define EPROC_NAME_OFF     0x174 // _EPROCESS.ImageFileName
  84. #define EPROC_PEB_OFF      0x1b0 // _EPROCESS.Peb
  85. #define PEB_LDR_OFF        0x00c // _PEB.Ldr
  86. #define PEB_LDR_MEM_LINKS_OFF  0x014 // _PEB_LDR_DATA.InMemoryOrderModuleList
  87. #define LDR_MEM_LINKS_OFF  0x008 // _LDR_DATA_TABLE_ENTRY.InMemoryOrderLinks
  88. #define LDR_BASE_OFF       0x018 // _LDR_DATA_TABLE_ENTRY.DllBase
  89. #define LDR_SIZE_OFF       0x020 // _LDR_DATA_TABLE_ENTRY.SizeOfImage
  90. #define LDR_FILENAME_OFF   0x024 // _LDR_DATA_TABLE_ENTRY.FullDllName
  91. #define LDR_BASENAME_OFF   0x02c // _LDR_DATA_TABLE_ENTRY.BaseDllName
  92.  
  93. // Size of a guest pointer. Note that this can't just be target_ulong since
  94. // a 32-bit OS will run on x86_64-softmmu
  95. #define PTR uint32_t
  96.  
  97.  
  98. // Check if the instruction is sysenter (0F 34)
  99. bool translate_callback(CPUState *env, target_ulong pc) {
  100.     unsigned char buf[2];
  101.     cpu_memory_rw_debug(env, pc, buf, 2, 0);
  102.     if (buf[0] == 0xC3)
  103.         return true;
  104.     else
  105.         return false;
  106. }
  107.  
  108. // This will only be called for instructions where the
  109. // translate_callback returned true
  110. int exec_callback(CPUState *env, target_ulong pc) {
  111. #ifdef TARGET_I386
  112.     // On Windows and Linux, the system call id is in EAX  
  113.     //        __asm__("int3");
  114.     unsigned char buf[4];
  115.     cpu_memory_rw_debug(env, env->regs[R_ESP], buf, 4, 0);
  116.    
  117.     std::stringstream ss;
  118.     ss << "0x";
  119.    
  120.     for ( size_t i = 0; i < 4; ++i )
  121.         ss << std::hex << std::uppercase << std::setfill( '0' ) << std::setw( 2 * sizeof( BYTE ) ) << static_cast< unsigned >( buf[ i ] );
  122.        
  123.     std::string str = ss.str();
  124.    
  125.     OsiProcs *ps;
  126.     OsiModules *ms;
  127.     uint32_t i;
  128.  
  129.     on_get_processes(env, &ps);
  130.     if(pc > 0x8000000) 
  131.         for (i=0; i< ps->num; i++) {
  132.             on_get_libraries(env, &ps->proc[i], &ms);
  133.         }
  134.    
  135.    
  136. #endif
  137.     return 0;
  138. }
  139.  
  140.  
  141. static inline char * make_pagedstr() {
  142.     char *m = (char *)malloc(8);
  143.     strcpy(m, "(paged)");
  144.     return m;
  145. }
  146.  
  147. // Gets a unicode string. Does its own mem allocation.
  148. // Output is a null-terminated UTF8 string
  149. char * get_unicode_str(CPUState *env, PTR ustr) {
  150.     uint16_t size = 0;
  151.     PTR str_ptr = 0;
  152.     if (-1 == panda_virtual_memory_rw(env, ustr, (uint8_t *)&size, 2, false)) {
  153.         return make_pagedstr();
  154.     }
  155.     // Clamp size
  156.     if (size > 1024) size = 1024;
  157.     if (-1 == panda_virtual_memory_rw(env, ustr+4, (uint8_t *)&str_ptr, 4, false)) {
  158.         return make_pagedstr();
  159.     }
  160.     gchar *in_str = (gchar *)g_malloc0(size);
  161.     if (-1 == panda_virtual_memory_rw(env, str_ptr, (uint8_t *)in_str, size, false)) {
  162.         g_free(in_str);
  163.         return make_pagedstr();
  164.     }
  165.  
  166.     gsize bytes_written = 0;
  167.     gchar *out_str = g_convert(in_str, size,
  168.             "UTF-8", "UTF-16LE", NULL, &bytes_written, NULL);
  169.  
  170.     // An abundance of caution: we copy it over to something allocated
  171.     // with our own malloc. In the future we need to provide a way for
  172.     // someone else to free the memory allocated in here...
  173.     char *ret = (char *)malloc(bytes_written+1);
  174.     memcpy(ret, out_str, bytes_written+1);
  175.     g_free(in_str);
  176.     g_free(out_str);
  177.     return ret;
  178. }
  179.  
  180. // Process introspection
  181. static PTR get_next_proc(CPUState *env, PTR eproc) {
  182.     PTR next;
  183.     if (-1 == panda_virtual_memory_rw(env, eproc+EPROC_LINKS_OFF, (uint8_t *)&next, sizeof(PTR), false))
  184.         return 0;
  185.     next -= EPROC_LINKS_OFF;
  186.     return next;
  187. }
  188.  
  189. static PTR get_pid(CPUState *env, PTR eproc) {
  190.     PTR pid;
  191.     panda_virtual_memory_rw(env, eproc+EPROC_PID_OFF, (uint8_t *)&pid, sizeof(PTR), false);
  192.     return pid;
  193. }
  194.  
  195. static PTR get_ppid(CPUState *env, PTR eproc) {
  196.     PTR ppid;
  197.     panda_virtual_memory_rw(env, eproc+EPROC_PPID_OFF, (uint8_t *)&ppid, sizeof(PTR), false);
  198.     return ppid;
  199. }
  200.  
  201. static PTR get_dtb(CPUState *env, PTR eproc) {
  202.     PTR dtb;
  203.     panda_virtual_memory_rw(env, eproc+EPROC_DTB_OFF, (uint8_t *)&dtb, sizeof(PTR), false);
  204.     return dtb;
  205. }
  206.  
  207. // *must* be called on a buffer of size 16 or greater
  208. static void get_procname(CPUState *env, PTR eproc, char *name) {
  209.     panda_virtual_memory_rw(env, eproc+EPROC_NAME_OFF, (uint8_t *)name, 15, false);
  210.     name[15] = '\0';
  211. }
  212.  
  213. // XXX: this will have to change for 64-bit
  214. static PTR get_current_proc(CPUState *env) {
  215.     // Read the kernel-mode FS segment base
  216.     uint32_t e1, e2;
  217.     uint32_t fs_base, thread, proc;
  218.  
  219.     // Read out the two 32-bit ints that make up a segment descriptor
  220.     panda_virtual_memory_rw(env, env->gdt.base + KMODE_FS, (uint8_t *)&e1, sizeof(PTR), false);
  221.     panda_virtual_memory_rw(env, env->gdt.base + KMODE_FS + 4, (uint8_t *)&e2, sizeof(PTR), false);
  222.    
  223.     // Turn wacky segment into base
  224.     fs_base = (e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000);
  225.  
  226.     // Read KPCR->CurrentThread->Process
  227.     panda_virtual_memory_rw(env, fs_base+KPCR_CURTHREAD_OFF, (uint8_t *)&thread, sizeof(PTR), false);
  228.     panda_virtual_memory_rw(env, thread+KTHREAD_KPROC_OFF, (uint8_t *)&proc, sizeof(PTR), false);
  229.  
  230.     return proc;
  231. }
  232.  
  233. static bool is_valid_process(CPUState *env, PTR eproc) {
  234.     uint8_t type;
  235.     uint8_t size;
  236.    
  237.     panda_virtual_memory_rw(env, eproc+EPROC_TYPE_OFF, (uint8_t *)&type, 1, false);
  238.     panda_virtual_memory_rw(env, eproc+EPROC_SIZE_OFF, (uint8_t *)&size, 1, false);
  239.  
  240.     return (type == EPROC_TYPE && size == EPROC_SIZE);
  241. }
  242.  
  243. // Module stuff
  244. static const char *get_mod_basename(CPUState *env, PTR mod) {
  245.     return get_unicode_str(env, mod+LDR_BASENAME_OFF);
  246. }
  247.  
  248. static const char *get_mod_filename(CPUState *env, PTR mod) {
  249.     return get_unicode_str(env, mod+LDR_FILENAME_OFF);
  250. }
  251.  
  252. static PTR get_mod_base(CPUState *env, PTR mod) {
  253.     PTR base;
  254.     panda_virtual_memory_rw(env, mod+LDR_BASE_OFF, (uint8_t *)&base, sizeof(PTR), false);
  255.     return base;
  256. }
  257.  
  258. static PTR get_mod_size(CPUState *env, PTR mod) {
  259.     uint32_t size;
  260.     panda_virtual_memory_rw(env, mod+LDR_SIZE_OFF, (uint8_t *)&size, sizeof(uint32_t), false);
  261.     return size;
  262. }
  263.  
  264. static PTR get_next_mod(CPUState *env, PTR mod) {
  265.     PTR next;
  266.     if (-1 == panda_virtual_memory_rw(env, mod+LDR_MEM_LINKS_OFF, (uint8_t *)&next, sizeof(PTR), false))
  267.         return 0;
  268.     next -= LDR_MEM_LINKS_OFF;
  269.     return next;
  270. }
  271.  
  272. static void fill_osiproc(CPUState *env, OsiProc *p, PTR eproc) {
  273.     p->offset = eproc;
  274.     char *name = (char *)malloc(16);
  275.     get_procname(env, eproc, name);
  276.     p->name = name;
  277.     p->asid = get_dtb(env, eproc);
  278.     p->pages = NULL;
  279.     p->pid = get_pid(env, eproc);
  280.     p->ppid = get_ppid(env, eproc);
  281. }
  282.  
  283. static void fill_osimod(CPUState *env, OsiModule *m, PTR mod) {
  284.     m->offset = mod;
  285.     m->file = (char *)get_mod_filename(env, mod);
  286.     m->base = get_mod_base(env, mod);
  287.     m->size = get_mod_size(env, mod);
  288.     m->name = (char *)get_mod_basename(env, mod);
  289. }
  290.  
  291. static void add_proc(CPUState *env, OsiProcs *ps, PTR eproc) {
  292.     static uint32_t capacity = 16;
  293.     if (ps->proc == NULL) {
  294.         ps->proc = (OsiProc *)malloc(sizeof(OsiProc) * capacity);
  295.     }
  296.     else if (ps->num == capacity) {
  297.         capacity *= 2;
  298.         ps->proc = (OsiProc *)realloc(ps->proc, sizeof(OsiProc) * capacity);
  299.     }
  300.  
  301.     OsiProc *p = &ps->proc[ps->num++];
  302.     fill_osiproc(env, p, eproc);
  303. }
  304.  
  305. static void add_mod(CPUState *env, OsiModules *ms, PTR mod) {
  306.     static uint32_t capacity = 16;
  307.     if (ms->module == NULL) {
  308.         ms->module = (OsiModule *)malloc(sizeof(OsiModule) * capacity);
  309.     }
  310.     else if (ms->num == capacity) {
  311.         capacity *= 2;
  312.         ms->module = (OsiModule *)realloc(ms->module, sizeof(OsiModule) * capacity);
  313.     }
  314.  
  315.     OsiModule *p = &ms->module [ms->num++];
  316.     fill_osimod(env, p, mod);
  317. }
  318.  
  319. void on_get_current_process(CPUState *env, OsiProc **out_p) {
  320.     OsiProc *p = (OsiProc *) malloc(sizeof(OsiProc));
  321.     PTR eproc = get_current_proc(env);
  322.  
  323.     /*
  324.         Since I'm using KTHREAD_KPROC_OFF as an ETHREAD, check to make
  325.         sure this is a kernel thread that has an associated user process.
  326.     */
  327.     while (!is_valid_process(env,eproc))
  328.     {
  329.         eproc = get_next_proc(env, eproc);
  330.  
  331.         if (!eproc) break;
  332.     }
  333.  
  334.     if (!eproc)
  335.     {
  336.         p->name = NULL; //free_osiproc still has to work properly
  337.     }
  338.     else
  339.     {
  340.         fill_osiproc(env, p, eproc);
  341.     }
  342.  
  343.     *out_p = p;
  344. }
  345.  
  346. void on_get_processes(CPUState *env, OsiProcs **out_ps) {
  347.     PTR first = get_current_proc(env);
  348.     PTR first_pid = get_pid(env, first);
  349.     PTR current = first;
  350.  
  351.     if (first_pid == 0) { // Idle proc, don't try
  352.         out_ps = NULL;
  353.         return;
  354.     }
  355.  
  356.     OsiProcs *ps = (OsiProcs *)malloc(sizeof(OsiProcs));
  357.     ps->num = 0;
  358.     ps->proc = NULL;
  359.  
  360.     do {
  361.         // One of these will be the loop head,
  362.         // which we don't want to include
  363.         /*
  364.             Since I'm using KTHREAD_KPROC_OFF as an ETHREAD, check to make
  365.             sure this is a kernel thread that has an associated user process.
  366.         */
  367.         if (is_valid_process(env, current)) {
  368.             add_proc(env, ps, current);
  369.         }
  370.  
  371.         current = get_next_proc(env, current);
  372.         if (!current) break;
  373.     } while (current != first);
  374.  
  375.     *out_ps = ps;
  376. }
  377.  
  378. void on_get_libraries(CPUState *env, OsiProc *p, OsiModules **out_ms) {
  379.     // Find the process we're interested in
  380.     PTR eproc = get_current_proc(env);
  381.     bool found = false;
  382.     PTR first_proc = eproc;
  383.     do {
  384.         if (eproc == p->offset) {
  385.             found = true;
  386.             break;
  387.         }
  388.         eproc = get_next_proc(env, eproc);
  389.         if (!eproc) break;
  390.     } while (eproc != first_proc);
  391.  
  392.     if (!found) {
  393.         *out_ms = NULL; return;
  394.     }
  395.  
  396.     OsiModules *ms = (OsiModules *)malloc(sizeof(OsiModules));
  397.     ms->num = 0;
  398.     ms->module = NULL;
  399.     PTR peb = 0, ldr = 0;
  400.     // PEB->Ldr->InMemoryOrderModuleList
  401.     if (-1 == panda_virtual_memory_rw(env, eproc+EPROC_PEB_OFF, (uint8_t *)&peb, sizeof(PTR), false) ||
  402.         -1 == panda_virtual_memory_rw(env, peb+PEB_LDR_OFF, (uint8_t *)&ldr, sizeof(PTR), false)) {
  403.         *out_ms = NULL; return;
  404.     }
  405.  
  406.     // Fake "first mod": the address of where the list list head would
  407.     // be if it were a LDR_DATA_TABLE_ENTRY
  408.     PTR first_mod = ldr+PEB_LDR_MEM_LINKS_OFF-LDR_MEM_LINKS_OFF;
  409.     PTR current_mod = get_next_mod(env, first_mod);
  410.     // We want while loop here -- we are starting at the head,
  411.     // which is not a valid module
  412.     while (current_mod != first_mod) {
  413.         add_mod(env, ms, current_mod);
  414.         current_mod = get_next_mod(env, current_mod);
  415.         if (!current_mod) break;
  416.     }
  417.  
  418.     *out_ms = ms;
  419.     return;
  420. }
  421.  
  422. void on_free_osiproc(OsiProc *p) {
  423.     if (!p) return;
  424.     if (p->name) free(p->name);
  425.     free(p);
  426. }
  427.  
  428. void on_free_osiprocs(OsiProcs *ps) {
  429.     if (!ps) return;
  430.     for(uint32_t i = 0; i < ps->num; i++) {
  431.         free(ps->proc[i].name);
  432.     }
  433.     if(ps->proc) free(ps->proc);
  434.     free(ps);
  435. }
  436.  
  437. void on_free_osimodules(OsiModules *ms) {
  438.     if (!ms) return;
  439.     for(uint32_t i = 0; i < ms->num; i++) {
  440.         free(ms->module[i].file);
  441.         free(ms->module[i].name);
  442.     }
  443.     if (ms->module) free(ms->module);
  444.     free(ms);
  445. }
  446.  
  447. #endif
  448.  
  449. bool init_plugin(void *self) {
  450.     panda_require("osi");
  451. #ifdef TARGET_I386
  452.     printf("Initializing plugin osi winxp\n");
  453.    
  454.     PPP_REG_CB("osi", on_get_current_process, on_get_current_process);
  455.     PPP_REG_CB("osi", on_get_processes, on_get_processes);
  456.     PPP_REG_CB("osi", on_get_libraries, on_get_libraries);
  457.     PPP_REG_CB("osi", on_free_osiproc, on_free_osiproc);
  458.     PPP_REG_CB("osi", on_free_osiprocs, on_free_osiprocs);
  459.     PPP_REG_CB("osi", on_free_osimodules, on_free_osimodules);
  460.    
  461.     panda_cb pcb;
  462.    
  463.     pcb.insn_translate = translate_callback;
  464.     panda_register_callback(self, PANDA_CB_INSN_TRANSLATE, pcb);
  465.     pcb.insn_exec = exec_callback;
  466.     panda_register_callback(self, PANDA_CB_INSN_EXEC, pcb);
  467.    
  468. #endif
  469.     plugin_log = fopen("rets.txt", "w");    
  470.     if(!plugin_log) return false;
  471.     else return true;
  472.    
  473.     return true;
  474. }
  475.  
  476. void uninit_plugin(void *self)
  477. {
  478.         fclose(plugin_log);
  479.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement