Advertisement
Guest User

memscan.c

a guest
Dec 16th, 2012
6,141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.53 KB | None | 0 0
  1. #include <windows.h>
  2. #include <stdio.h>
  3.  
  4. #define IS_IN_SEARCH(mb,offset) (mb->searchmask[(offset)/8] & (1<<((offset)%8)))
  5. #define REMOVE_FROM_SEARCH(mb,offset) mb->searchmask[(offset)/8] &= ~(1<<((offset)%8));
  6.  
  7. typedef struct _MEMBLOCK
  8. {
  9.     HANDLE hProc;
  10.     unsigned char *addr;
  11.     int size;
  12.     unsigned char *buffer;
  13.  
  14.     unsigned char *searchmask;
  15.     int matches;
  16.     int data_size;
  17.  
  18.     struct _MEMBLOCK *next;
  19. } MEMBLOCK;
  20.  
  21. typedef enum
  22. {
  23.     COND_UNCONDITIONAL,
  24.     COND_EQUALS,
  25.  
  26.     COND_INCREASED,
  27.     COND_DECREASED,
  28. } SEARCH_CONDITION;
  29.  
  30.  
  31. // Enable or disable a privilege in an access token
  32. // source: http://msdn.microsoft.com/en-us/library/aa446619(VS.85).aspx
  33. BOOL SetPrivilege(
  34.     HANDLE hToken,          // access token handle
  35.     LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
  36.     BOOL bEnablePrivilege   // to enable or disable privilege
  37.     )
  38. {
  39.     TOKEN_PRIVILEGES tp;
  40.     LUID luid;
  41.  
  42.     if ( !LookupPrivilegeValue(
  43.             NULL,            // lookup privilege on local system
  44.             lpszPrivilege,   // privilege to lookup
  45.             &luid ) )        // receives LUID of privilege
  46.     {
  47.         printf("LookupPrivilegeValue error: %u\n", GetLastError() );
  48.         return FALSE;
  49.     }
  50.  
  51.     tp.PrivilegeCount = 1;
  52.     tp.Privileges[0].Luid = luid;
  53.     if (bEnablePrivilege)
  54.         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  55.     else
  56.         tp.Privileges[0].Attributes = 0;
  57.  
  58.     // Enable the privilege or disable all privileges.
  59.  
  60.     if ( !AdjustTokenPrivileges(
  61.            hToken,
  62.            FALSE,
  63.            &tp,
  64.            sizeof(TOKEN_PRIVILEGES),
  65.            (PTOKEN_PRIVILEGES) NULL,
  66.            (PDWORD) NULL) )
  67.     {
  68.           printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
  69.           return FALSE;
  70.     }
  71.  
  72.     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
  73.  
  74.     {
  75.           printf("The token does not have the specified privilege. \n");
  76.           return FALSE;
  77.     }
  78.  
  79.     return TRUE;
  80. }
  81.  
  82. MEMBLOCK* create_memblock (HANDLE hProc, MEMORY_BASIC_INFORMATION *meminfo, int data_size)
  83. {
  84.     MEMBLOCK *mb = malloc (sizeof(MEMBLOCK));
  85.  
  86.     if (mb)
  87.     {
  88.         mb->hProc = hProc;
  89.         mb->addr = meminfo->BaseAddress;
  90.         mb->size = meminfo->RegionSize;
  91.         mb->buffer = malloc (meminfo->RegionSize);
  92.         mb->searchmask = malloc (meminfo->RegionSize/8);
  93.         memset (mb->searchmask, 0xff, meminfo->RegionSize/8);
  94.         mb->matches = meminfo->RegionSize;
  95.         mb->data_size = data_size;
  96.         mb->next = NULL;
  97.     }
  98.  
  99.     return mb;
  100. }
  101.  
  102. void free_memblock (MEMBLOCK *mb)
  103. {
  104.     if (mb)
  105.     {
  106.         if (mb->buffer)
  107.         {
  108.             free (mb->buffer);
  109.         }
  110.  
  111.         if (mb->searchmask)
  112.         {
  113.             free (mb->searchmask);
  114.         }
  115.  
  116.         free (mb);
  117.     }
  118. }
  119.  
  120.  
  121. void update_memblock (MEMBLOCK *mb, SEARCH_CONDITION condition, unsigned int val)
  122. {
  123.     static unsigned char tempbuf[128*1024];
  124.     unsigned int bytes_left;
  125.     unsigned int total_read;
  126.     unsigned int bytes_to_read;
  127.     unsigned int bytes_read;
  128.  
  129.     if (mb->matches > 0)
  130.     {
  131.         bytes_left = mb->size;
  132.         total_read = 0;
  133.         mb->matches = 0;
  134.    
  135.         while (bytes_left)
  136.         {
  137.             bytes_to_read = (bytes_left > sizeof(tempbuf)) ? sizeof(tempbuf) : bytes_left;
  138.             ReadProcessMemory (mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, (DWORD*)&bytes_read);
  139.             if (bytes_read != bytes_to_read) break;
  140.    
  141.             if (condition == COND_UNCONDITIONAL)
  142.             {
  143.                 memset (mb->searchmask + (total_read/8), 0xff, bytes_read/8);
  144.                 mb->matches += bytes_read;
  145.             }
  146.             else
  147.             {
  148.                 unsigned int offset;
  149.    
  150.                 for (offset = 0; offset < bytes_read; offset += mb->data_size)
  151.                 {
  152.                     if (IS_IN_SEARCH(mb,(total_read+offset)))
  153.                     {
  154.                         BOOL is_match = FALSE;
  155.                         unsigned int temp_val;
  156.                         unsigned int prev_val = 0;
  157.    
  158.                         switch (mb->data_size)
  159.                         {
  160.                             case 1:
  161.                                 temp_val = tempbuf[offset];
  162.                                 prev_val = *((unsigned char*)&mb->buffer[total_read+offset]);
  163.                                 break;
  164.                             case 2:
  165.                                 temp_val = *((unsigned short*)&tempbuf[offset]);
  166.                                 prev_val = *((unsigned short*)&mb->buffer[total_read+offset]);
  167.                                 break;
  168.                             case 4:
  169.                             default:
  170.                                 temp_val = *((unsigned int*)&tempbuf[offset]);
  171.                                 prev_val = *((unsigned int*)&mb->buffer[total_read+offset]);
  172.                                 break;
  173.                         }
  174.    
  175.                         switch (condition)
  176.                         {
  177.                             case COND_EQUALS:
  178.                                 is_match = (temp_val == val);
  179.                                 break;
  180.                             case COND_INCREASED:
  181.                                 is_match = (temp_val > prev_val);
  182.                                 break;
  183.                             case COND_DECREASED:
  184.                                 is_match = (temp_val < prev_val);
  185.                                 break;
  186.                             default:
  187.                                 break;
  188.                         }
  189.    
  190.                         if (is_match)
  191.                         {
  192.                             mb->matches++;
  193.                         }
  194.                         else
  195.                         {
  196.                             REMOVE_FROM_SEARCH(mb,(total_read+offset));
  197.                         }
  198.                     }
  199.                 }
  200.             }
  201.    
  202.             memcpy (mb->buffer + total_read, tempbuf, bytes_read);
  203.    
  204.             bytes_left -= bytes_read;
  205.             total_read += bytes_read;
  206.         }
  207.    
  208.         mb->size = total_read;
  209.     }
  210. }
  211.  
  212.  
  213.  
  214. MEMBLOCK* create_scan (unsigned int pid, int data_size)
  215. {
  216.     MEMBLOCK *mb_list = NULL;
  217.     MEMORY_BASIC_INFORMATION meminfo;
  218.     unsigned char *addr = 0;
  219.  
  220.     HANDLE hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
  221.     DWORD error  = GetLastError();
  222.  
  223.     if (hProc)
  224.     {
  225.         while (1)
  226.         {
  227.             if (VirtualQueryEx (hProc, addr, &meminfo, sizeof(meminfo)) == 0)
  228.             {
  229.                 break;
  230.             }
  231. #define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
  232.             if ((meminfo.State & MEM_COMMIT) && (meminfo.Protect & WRITABLE))
  233.             {
  234.                 MEMBLOCK *mb = create_memblock (hProc, &meminfo, data_size);
  235.                 if (mb)
  236.                 {
  237.                     mb->next = mb_list;
  238.                     mb_list = mb;
  239.                 }
  240.             }
  241.             addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;
  242.         }
  243.     }
  244.     else
  245.         printf ("Failed to open process - error - %d\r\n", error);
  246.  
  247.     return mb_list;
  248. }
  249.  
  250.  
  251. void free_scan (MEMBLOCK *mb_list)
  252. {
  253.     CloseHandle (mb_list->hProc);
  254.  
  255.     while (mb_list)
  256.     {
  257.         MEMBLOCK *mb = mb_list;
  258.         mb_list = mb_list->next;
  259.         free_memblock (mb);
  260.     }
  261. }
  262.  
  263. void update_scan (MEMBLOCK *mb_list, SEARCH_CONDITION condition, unsigned int val)
  264. {
  265.     MEMBLOCK *mb = mb_list;
  266.     while (mb)
  267.     {
  268.         update_memblock (mb, condition, val);
  269.         mb = mb->next;
  270.     }
  271. }
  272.  
  273.  
  274. void dump_scan_info (MEMBLOCK *mb_list)
  275. {
  276.     MEMBLOCK *mb = mb_list;
  277.  
  278.     while (mb)
  279.     {
  280.         int i;
  281.         printf ("0x%08x %d\r\n", mb->addr, mb->size);
  282.  
  283.         for (i = 0; i < mb->size; i++)
  284.         {
  285.             printf ("%02x", mb->buffer[i]);
  286.         }
  287.         printf ("\r\n");
  288.  
  289.         mb = mb->next;
  290.     }
  291. }
  292.  
  293.  
  294. void poke (HANDLE hProc, int data_size, unsigned int addr, unsigned int val)
  295. {
  296.     if (WriteProcessMemory (hProc, (void*)addr, &val, data_size, NULL) == 0)
  297.     {
  298.         printf ("poke failed\r\n");
  299.     }
  300. }
  301.  
  302. unsigned int peek (HANDLE hProc, int data_size, unsigned int addr)
  303. {
  304.     unsigned int val = 0;
  305.  
  306.     if (ReadProcessMemory (hProc, (void*)addr, &val, data_size, NULL) == 0)
  307.     {
  308.         printf ("peek failed\r\n");
  309.     }
  310.  
  311.     return val;
  312. }
  313.  
  314.  
  315. void print_matches (MEMBLOCK *mb_list)
  316. {
  317.     unsigned int offset;
  318.     MEMBLOCK *mb = mb_list;
  319.  
  320.     while (mb)
  321.     {
  322.         for (offset = 0; offset < mb->size; offset += mb->data_size)
  323.         {
  324.             if (IS_IN_SEARCH(mb,offset))
  325.             {
  326.                 unsigned int val = peek (mb->hProc, mb->data_size, (unsigned int)mb->addr + offset);
  327.                 printf ("0x%08x: 0x%08x (%d) \r\n", mb->addr + offset, val, val);
  328.             }
  329.         }
  330.  
  331.         mb = mb->next;
  332.     }
  333. }
  334.  
  335.  
  336. int get_match_count (MEMBLOCK *mb_list)
  337. {
  338.     MEMBLOCK *mb = mb_list;
  339.     int count = 0;
  340.  
  341.     while (mb)
  342.     {
  343.         count += mb->matches;
  344.         mb = mb->next;
  345.     }
  346.  
  347.     return count;
  348. }
  349.  
  350.  
  351.  
  352. unsigned int str2int (char *s)
  353. {
  354.     int base = 10;
  355.  
  356.     if (s[0] == '0' && s[1] == 'x')
  357.     {
  358.         base = 16;
  359.         s += 2;
  360.     }
  361.  
  362.     return strtoul (s, NULL, base);
  363. }
  364.  
  365.  
  366. MEMBLOCK* ui_new_scan(void)
  367. {
  368.     MEMBLOCK *scan = NULL;
  369.     DWORD pid;
  370.     int data_size;
  371.     unsigned int start_val;
  372.     SEARCH_CONDITION start_cond;
  373.     char s[20];
  374.  
  375.     while(1)
  376.     {
  377.         printf ("\r\nEnter the pid: ");
  378.         fgets (s,sizeof(s),stdin);
  379.         pid = str2int (s);
  380.         printf ("\r\nEnter the data size: ");
  381.         fgets (s,sizeof(s),stdin);
  382.         data_size = str2int (s);
  383.         printf ("\r\nEnter the start value, or 'u' for unknown: ");
  384.         fgets (s,sizeof(s),stdin);
  385.         if (s[0] == 'u')
  386.         {
  387.             start_cond = COND_UNCONDITIONAL;
  388.             start_val = 0;
  389.         }
  390.         else
  391.         {
  392.             start_cond = COND_EQUALS;
  393.             start_val = str2int (s);
  394.         }
  395.  
  396.         scan = create_scan (pid, data_size);
  397.         if (scan) break;
  398.         printf ("\r\nInvalid scan");
  399.     }
  400.  
  401.     update_scan (scan, start_cond, start_val);
  402.     printf ("\r\n%d matches found\r\n", get_match_count(scan));
  403.  
  404.     return scan;
  405. }
  406.  
  407.  
  408. void ui_poke (HANDLE hProc, int data_size)
  409. {
  410.     unsigned int addr;
  411.     unsigned int val;
  412.     char s[20];
  413.  
  414.     printf ("Enter the address: ");
  415.     fgets (s,sizeof(s),stdin);
  416.     addr = str2int (s);
  417.  
  418.     printf ("\r\nEnter the value: ");
  419.     fgets (s,sizeof(s),stdin);
  420.     val = str2int (s);
  421.     printf ("\r\n");
  422.  
  423.     poke (hProc, data_size, addr, val);
  424. }
  425.  
  426.  
  427. void ui_run_scan(void)
  428. {
  429.     unsigned int val;
  430.     char s[20];
  431.     MEMBLOCK *scan;
  432.  
  433.     scan = ui_new_scan();
  434.  
  435.     while (1)
  436.     {
  437.         printf ("\r\nEnter the next value or");
  438.         printf ("\r\n[i] increased");
  439.         printf ("\r\n[d] decreased");
  440.         printf ("\r\n[m] print matches");
  441.         printf ("\r\n[p] poke address");
  442.         printf ("\r\n[n] new scan");
  443.         printf ("\r\n[q] quit\r\n");
  444.  
  445.         fgets(s,sizeof(s),stdin);
  446.         printf ("\r\n");
  447.  
  448.         switch (s[0])
  449.         {
  450.             case 'i':
  451.                 update_scan (scan, COND_INCREASED, 0);
  452.                 printf ("%d matches found\r\n", get_match_count(scan));
  453.                 break;
  454.             case 'd':
  455.                 update_scan (scan, COND_DECREASED, 0);
  456.                 printf ("%d matches found\r\n", get_match_count(scan));
  457.                 break;
  458.             case 'm':
  459.                 print_matches (scan);
  460.                 break;
  461.             case 'p':
  462.                 ui_poke (scan->hProc, scan->data_size);
  463.                 break;
  464.             case 'n':
  465.                 free_scan (scan);
  466.                 scan = ui_new_scan();
  467.                 break;
  468.             case 'q':
  469.                 free_scan (scan);
  470.                 return;
  471.             default:
  472.                 val = str2int (s);
  473.                 update_scan (scan, COND_EQUALS, val);
  474.                 printf ("%d matches found\r\n", get_match_count(scan));
  475.                 break;
  476.         }
  477.     }
  478. }
  479.  
  480.  
  481.  
  482.  
  483. int main (int argc, char *argv[])
  484. {
  485.     // get process handle
  486.     HANDLE hProc = GetCurrentProcess();
  487.  
  488.     // get access token of process
  489.     HANDLE hToken = NULL;
  490.     if (!OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, &hToken))
  491.          printf ("Failed to open access token");
  492.  
  493.     // set token privileges to SE_DEBUG_NAME to able to access OpenProcess() with PROCESS_ALL_ACCESS
  494.     if (!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
  495.         printf ("Failed to set debug privilege");
  496.  
  497.     ui_run_scan();
  498.     return 0;
  499. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement