Jump to content
Nytro

Extracting Objects from a Running Process

Recommended Posts

Posted

[h=1]Extracting Objects from a Running Process[/h]February 11, 2013 By PnUic

Few days ago two new 0-days have been spotted in the wild: CVE-2013-0633 and CVE-2013-0634, both of them involving a .swf file, possibly embedded inside a Word Document. It might be interesting to understand how to dump a similar resource while the attacked process is running, after all the obfuscation layers are cleared. Clearly this same technique can be expanded to extract any type of object from any process, as an example whenever we need to simply dump a memory area, or when we need to extract (or find) an entire object. While memory dumpers are usually common tools, it might be interesting to understand how the dumping process works. So let’s dig a bit deeper.

[h=2]Step 1: Understanding Windows Address Space[/h] The virtual address space of a process is the set of virtual memory addresses that the process is allowed to use. In the default Virtual Address Space for 32-bit Windows processes, the lower 2GB: from 0×0 through 0x7FFFFFFF, are assigned to the running process while the other 2GB are normally used by the system.

More information: Virtual Address Space -Virtual Address Space in 64-bit Windows.

[h=2]Step 2: APIs to get system information and to access a process memory[/h] [h=3]2.1 Processes list[/h] In order to read a given process memory, we need to acquire its handle and in turn, to do that we need to iterate the list of processes until we find the one we are looking for. Process enumeration is performed through the use of EnunProcesses() API, the code is quite simple:

if(!EnumProcesses(nProcess,  //processes list
sizeof(nProcess),
&nByteOfProc))
{return false;}

nOfProcesses = nByteOfProc / sizeof(DWORD);

//for each process
for (i = 0; i < nOfProcesses; i++ )
{
// Get a handle to the process.
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, nProcess[i] );

// Get the process name.
if ( hProcess != NULL)
{
if (EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
{
//get application filename
GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR));

//Has it found the right process?
if(!_tcscmp(szProcessName, procName))
{
// Do whatever we need with the newly found process
...
}
}

CloseHandle(hProcess);
}

}

[h=3]2.2 Memory sections[/h] Once we have access to memory process throungh the handle, we need to get information on its sections in order to find in a signature (that is: a sequence of bytes).

That’s how we’ll proceed:

  1. Get the system minimum and maximum address of a process using GetSystemInfo
  2. Call VirtualQueryEx to retrieve information about sections within the virtual address space of a specified process, by section’s base address.

    1. System minimum address is the the first section base address.
    2. In the MEMORY_BASIC_INFORMATION structure there are info about memory section: size, base address and more;
    3. nextSectionBaseAddr = currentBaseAddress + currentSectionSize

    4. Copy in a locally allocated process memory the target process’ section (ReadProcessMemory) to find the desired signature with a simple memcmp().


      Here it is the code to find a sequence of bytes in memory: the SWF signature (the entire project can be downloaded at the end of the article).

      TCHAR buffer[] = _T("FWS"); //the signature can also be: CWS and ZWS, see SWF file format specification

      GetSystemInfo(&sysInfo);
      memBase = sysInfo.lpMinimumApplicationAddress;
      memMax = sysInfo.lpMaximumApplicationAddress;

      //until max memory address or until buffer found
      while(memBase < memMax) {

      //get section info
      VirtualQueryEx(hProcess, memBase, &mbi, sizeof(MEMORY_BASIC_INFORMATION));

      //if section is not reserved
      if(mbi.State != MEM_RESERVE )
      {
      //I copy it: I alloc a memory buffer in local process ..
      allocatedMem = (BYTE *) VirtualAlloc(NULL, mbi.RegionSize, MEM_COMMIT, PAGE_READWRITE);
      if(allocatedMem != NULL) {

      //.. and copy bytes for more scan velocity
      if(ReadProcessMemory(hProcess, memBase, allocatedMem, mbi.RegionSize, &jnk)) {
      storedBaseAddr = baseAddr = allocatedMem;
      maxAddr = (BYTE*) ( ((SIZE_T)baseAddr + mbi.RegionSize) - lenBuffer);

      //and find the buffer into section
      while(baseAddr < maxAddr) {
      if(memcmp((LPVOID)baseAddr, buffer, lenBuffer) == 0) {

      //I found it!!
      _tprintf(_T("\tBuffer found at found at %p\n"), ( (SIZE_T)memBase + (baseAddr-storedBaseAddr)) );

      //try to dump!
      DWORD objSize = dumpObj(baseAddr);
      //go ahead the object
      baseAddr = (BYTE*) ((SIZE_T)baseAddr + objSize);

      } else
      baseAddr++; //next byte
      }
      }

      //free memory
      VirtualFree(allocatedMem, 0, MEM_RELEASE);
      }
      }

      //next section base address
      memBase = (LPVOID) ((SIZE_T)memBase + mbi.RegionSize);
      }
      //the signature to find

      [h=3]2.3 Dump the object[/h] Once we have found a signature in memory, we can dump the object, provided we know its size and where to find this information: according to SWF specification the length field is an UInt32 (DWORD) at start+4:

      stringBaseAddr += 4;

      //get file size
      DWORD size = *((DWORD*)stringBaseAddr);
      _tprintf(_T("\tFile size: %u bytes\n"), size);

      //go to object start addr
      stringBaseAddr -= 4;

      //create a new file
      HANDLE hFile = CreateFile(outputFileName,GENERIC_WRITE, FILE_SHARE_WRITE, 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
      if (hFile == INVALID_HANDLE_VALUE) {
      _tprintf(_T("\tImpossible to create dump file\n"));
      return;
      }

      //and write in the object
      if(WriteFile(hFile, stringBaseAddr, size, &jnk, NULL) == false) {
      CloseHandle(hFile);
      DeleteFile(outputFileName);
      _tprintf(_T("\tImpossible to dump the file\n\n"));
      } else {
      CloseHandle(hFile);
      _tprintf(_T("\tFile dumped!!\n\n"));
      }
      //addr of "FileLength" field:

      That’s all!
      Download project’s code.
      Pn
      Sursa: Extracting Objects from a Running Process

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...