Environment Configuration
The overall architecture of remote debugging is as shown in the figure below.
Since the Windows debugger cannot be run on a Mac, remote debugging can be used to debug through a Mac.
First, copy the packed file and remote debugging service file to the TARGET (win10)
machine, and the remote debugging service file is located in the dbgsrv directory.
The final structure of TARGET (win10)
is as follows.
The packed program is packed with upx and is a 32-bit program.
Remote Debugging
Before remote debugging, analyze the packed program PACKED_PRACTICA_1.EXE
locally on a Mac (ida7.0), select MANUAL LOAD for manual loading, and load all sections of the file.
Before running the debugger, the IDA loader will go to the entry point of the packed program.
Program entry point
Note: The database file IDB cannot be renamed.
Run the win32_remote.exe remote debugging server on TARGET (win10)
, and specify the IP address with -i.
Select Remote Windows debugger
as the debugger.
In Process options, enter the IP address and port of TARGET (win10)
in Hostname, enter the absolute path of the packed program in Application and Input file, enter the directory path in Directory, and click OK after the configuration is complete.
Open the debugger menu and select Start process. After the debugging starts, it will pause at the program entry point (Modified: A breakpoint needs to be set at 0x638ec to pause at this point).
The executable file has been randomized, so the addresses executed each time will change. Therefore, the dumping and rebuilding of the IAT must be completed in the same run, and the program cannot be closed halfway.
Open the segments tab and observe the first code section after the header. The starting address of this section is 631000 and the ending address is 238000.
Finding OEP
The first method is to try the text search function to search for the popad or popa instruction. In this program, a popa instruction can be found.
From the figure, it can be seen that the address 0x63146e is the OEP.
The second method is to find the OEP by covering the first section with an execution breakpoint learned earlier.
Double-click on the first section in the segment view to jump to 0x631000, and check the section data. The address is randomized, and the base address is not 0x401000, but the memory occupancy is 0x7000. The upx0 section is from 0x631000 to 0x638000, with a difference of 0x7000 bytes.
Set a breakpoint at the starting point of the upx0 section by pressing F2, which is 0x601000, and the breakpoint size is 0x7000.
Delete other breakpoints and leave only this breakpoint, and press F9 to start debugging.
The program pauses at this point. Confirm that it is consistent with the previous OEP position, and then delete this breakpoint and remove the red background.
Click on the Reanalyze program in the lower left corner of the interface to reanalyze the program.
The content after OEP is recognized by IDA as part of STUB, so it is not marked with sub_
but with loc_
.
Dumping and IAT Rebuilding
After finding the OEP, start dumping and rebuilding the IAT. First, check the file base address and highest address.
Here, the file base address is 0x630000 and the highest address is 0x63B000. Take out the dumping script file, modify the addresses in the file, and then load and run the script.
The script is as follows:
import idaapi
import idc
import struct
start_ea = 0x630000
end_ea = 0x63b000
step = 4 # Each address occupies 4 bytes
file_path = "dump.bin"
with open(file_path, "wb") as f:
for ea in range(start_ea, end_ea, step):
# Read 4 bytes of data at the specified address and convert it to little endian byte order
bin_data = struct.pack("<L", idaapi.get_32bit(ea))
f.write(bin_data)
After running, a dump file is generated (the script file runs on a Mac, so the dump file is also generated on the Mac).
Copy the dump.bin file to Windows and open it with peeditor.
Right-click on each section and select dumpfixer. After the operation is completed, change the .bin file extension to .exe, as shown below:
Open the dump.exe file with scylla and load the packed program process.
Enter the OEP address, which is 0x63146e, and then click IAT Autosearch and Get Imports. An unrecognized API function is found.
Add the base address to the API address, 0x630000 + 0x20d4 = 0x6320d4, and switch to hexadecimal view. It does not look like part of the IAT.
Switch to the disassembly view to view the references at that location. The content is as follows:
Press x to display 2 references.
The address pointed to by 0x6320d4
only returns a RET instruction, as shown below:
The address pointed to by 0x6320d4
is a fixed address within the program, and it is only a RET instruction, not the referenced API function. Therefore, it can be deleted. In Syclla, right-click on the API function error and select CUT THUNK to remove it from the IAT.
After deletion, it looks like this:
Finally, click Fix Dump to rebuild the IAT for dump.exe, and finally generate the executable program dump_SCY.exe.
If dump_SCY.exe is run at this time, it will still flash a black screen and exit.
Cancel Random Base Address
Because the addresses generated at runtime other than the IAT are not redirected because they are always changing, this randomness needs to be eliminated. Open IDA, load the dump_SCY.exe file, use Manual Load to load the PE header section, and then go to this section.
In the header, find the Dll characteristics, and change its value to 0.
Open the Edit menu, select Patch Program, and change the word to 0.
Click OK, and then use Apply Patches to Input File to save the changes back to the executable file.
At this point, running dump_SCY.exe
again will run successfully, indicating that the unpacked file has been executed successfully.