Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* RunPE unpacker - interestingmalware@gmail.com
- *
- * Based on the example at http://www.hex-rays.com/idapro/scriptable.htm
- */
- #include <idc.idc>
- // flag for CreateProcess()
- #define CREATE_SUSPENDED 0x4
- static main() {
- auto code, bptea;
- auto esp, flags;
- auto buffer;
- auto filename = "unpacked.exe";
- // ignore EXCEPTION_FLT_INEXACT_RESULT. VB6 uses this a lot and usually
- // handles the exception, but it makes things a pain for debuggers
- SetExceptionFlags(0xC000008F, 0);
- Message("Starting process...\n");
- // launch the debugger and run until the entry point
- if (!RunTo(BeginEA()))
- return Warning("Can't debug to entrypoint");
- // wait until process is suspended
- code = GetDebuggerEvent(WFNE_SUSP, -1);
- if (code <= 0)
- return Warning("Can't get debugger event");
- // set breakpoint on CreateProcessW
- bptea = AddHardwareBp("kernel32_CreateProcessW");
- if(!bptea)
- return Warning("Can't break on CreateProcessW");
- // resume the execution and wait until CreateProcessW is called
- code = GetDebuggerEvent(WFNE_SUSP|WFNE_CONT, -1);
- if (code <= 0)
- return Warning("Can't resume execution for CreateProcessW breakpoint");
- DelBpt(bptea);
- // check arguments to CreateProcessW
- esp = GetRegValue("ESP");
- Message("CreateProcessW called from %.8X\n", Dword(esp));
- Message(" lpApplicationName: %s\n", GetString(Dword(esp+4), -1, ASCSTR_UNICODE));
- Message(" lpCommandLine: %s\n", GetString(Dword(esp+8), -1, ASCSTR_UNICODE));
- // make sure flags contain CREATE_SUSPENDED
- flags = Dword(esp+24);
- if(!(flags & CREATE_SUSPENDED)) {
- return Warning("Process created without CREATE_SUSPENDED flag (flag = %.8X)", flags);
- }
- // let the call to CreateProcessW finish - run until the return address is hit
- RunTo(Dword(esp));
- while(1) {
- code = GetDebuggerEvent(WFNE_SUSP|WFNE_CONT, -1);
- if (code <= 0)
- return Warning("Failed to let CreateProcessW finish");
- if(code != STEP) break;
- }
- // now break on calls to NtWriteVirtualMemory
- bptea = AddHardwareBp("ntdll_NtWriteVirtualMemory");
- if(!bptea)
- return Warning("Can't set breakpoint on NtWriteVirtualMemory");
- // resume the execution and wait until NtWriteVirtualMemory is called
- code = GetDebuggerEvent(WFNE_SUSP|WFNE_CONT, -1);
- if (code <= 0)
- return Warning("Can't resume execution for NtWriteVirtualMemory breakpoint");
- esp = GetRegValue("ESP");
- buffer = Dword(esp+12);
- DelBpt(bptea);
- Message("NtWriteVirtualMemory called from %.8X, buffer address: %.8X\n", Dword(esp), buffer);
- Message("Dumping file...\n");
- DumpPE(buffer, filename);
- }
- // add a hardware breakpoint at the specified name.
- // success: returns the address of the breakpoint
- // fail: returns 0
- static AddHardwareBp(name) {
- auto bptea;
- // get address of function
- bptea = LocByName(name);
- if (bptea == BADADDR) {
- Message ("Could not locate %s\n", name);
- return 0;
- }
- // set a hardware breakpoint
- Message("Setting a hardware breakpoint on %s\n", name);
- // XXX - this should check return value, but sometimes this call fails
- // even when the breakpoint is still set (in IDA 5.7)
- AddBptEx(bptea, 1, BPT_EXEC);
- //if(!AddBptEx(bptea, 1, BPT_EXEC)) {
- // Message("Failed to add hardware breakpoint for %s\n", name);
- // return 0;
- //}
- return bptea;
- }
- // for dump_pe()
- #define OPTHEADER_OFFSET 0x18
- #define SECTION_HEADER_SIZE 0x28
- // write a PE file stored in memory to disk. this function determines the size
- // of the PE file by calculating the offset of the end of the last section.
- // this can miss data stored by some PE files. there are probably better ways
- // to do this, but it works for me.
- static DumpPE(start_addr, filename) {
- auto nt_headers, num_secs, last_sec;
- auto end_addr;
- auto f, ptr;
- // check the DOS header magic value
- SetType(start_addr, "IMAGE_DOS_HEADER;");
- if(Word(start_addr.e_magic) != 0x5a4d) {
- Message("Not an EXE, invalid magic: %x\n", Word(start_addr.e_magic));
- return 0;
- }
- nt_headers = start_addr + Dword(start_addr.e_lfanew);
- SetType(nt_headers, "IMAGE_NT_HEADERS;");
- // check NT headers magic value
- if(Dword(nt_headers.Signature) != 0x4550) {
- Message("Not a PE, invalid signature: %x\n", Dword(nt_headers.Signature));
- return 0;
- }
- // figure out number of sections
- num_secs = Word(nt_headers.FileHeader.NumberOfSections);
- if(num_secs > 16) {
- Message("Sanity check failed, %i sections\n", num_secs);
- return;
- }
- // get offset of last section header
- last_sec = nt_headers + OPTHEADER_OFFSET + Word(nt_headers.FileHeader.SizeOfOptionalHeader) +
- (SECTION_HEADER_SIZE * (num_secs - 1));
- // figure out offset the end of the last section
- SetType(last_sec, "IMAGE_SECTION_HEADER;");
- end_addr = start_addr + Dword(last_sec.PointerToRawData) + Dword(last_sec.SizeOfRawData);
- // sanity check
- if(start_addr == end_addr) {
- Message("Something broke, start = end = %x\n", start_addr);
- return 0;
- }
- Message("Writing %i bytes to %s...\n", end_addr - start_addr, filename);
- // write the file
- f = fopen(filename, "wb");
- for(ptr=start_addr; ptr<end_addr; ptr++) {
- fputc(Byte(ptr), f);
- }
- fclose(f);
- Message("Done writing file\n");
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement