说明: Tron is a Windows XP driver that can create hidden views of arbitrary userland memory.
librootkit.c (34776, 2006-09-28)
librootkit.h (9516, 2006-09-28)
MAKEFILE (35, 2006-09-28)
SOURCES (82, 2006-09-28)
sysdefs.h (15523, 2006-09-28)
tron.c (71607, 2006-09-28)
tron_kernel.h (1091, 2006-09-28)
tron_user.h (5682, 2006-09-28)
This is Tron. He fights for the User.
v0.0.8 - ToorCon 8 Release
READ THIS ENTIRE FILE. BSODs ARE POSSIBLE IF YOU DO NOT!
Tron is a kernel driver that you can load into a WinXP system in order to
create hidden views of arbitrary userland memory. Win2k3 should be a pretty
easy port, as most offsets are unchanged, but it has not been tested.
To use Tron, load the sys file with a driver loader. There's one available at
The Code Project, or use the modified FUTo loader provided in conjunction with
this zip file.
Once the driver is loaded, programs can be written to create hidden views in
themselves or in other processes. The API exists in tron_user.h. Error status
is available via GetLastError(). The calls have no return value (they are
actually macros).
If you inspect the tron_user.h file, you can see that these calls are
implemented via a dual-nonce based hijack of VirtualAlloc. These nonces are
your "key" to Tron. You should change them from the default to guard against
programs scanning for Tron's presence by using the default nonce.
Note that the BASE_NONCE is much more fragile than the HANDLE_NONCE, since it
uses an argument verified in userland by VirtualAlloc. You are probably fine
just changing HANDLE_NONCE. Both nonces must match or the call is passed down
to the kernel. If you use CLU, it must be recompiled as well with your new
header.
Debug messages are available via Sysinternals DebugView. You can tune your
debugging level by removing the defines atop librootkit.h and recompiling.
You can also recompile Tron to log to a file with the LOG_TO_FILE define
in librootkit.h, and you can control the level of message severity as well.
WARNING
Tron is NOT SMP safe, and some APIs may have concurrency issues.
Tron should also not be considered stable for use on production machines.
Tron is a reverse engineering tool for people who know what they are doing.
I don't really care how you use or distribute Tron, but bear in mind that it
is not wise to ship it with general purpose end-user software or cracks. See
below for more information.
Tron is also 32bit ONLY, and a bug in VMWare (5.5.1) prevents you from running
hidden code in a virtual machine (VMWare's iret flushes ITLB). Hiding data
DOES work in vmware though. Microsoft's VirtualPC does not work at all.
API Description
1. ADD_CLOAK(pid, cloak_start, cloak_end, fake_start, fake_end)
ADD_CLOAK creates a hidden view in the process specified by pid from
cloak_start to cloak_end. The hidden view is masked behind the data at
fake_start to fake_end.
If the fake addresses are zero, the cloaked region appears to userland as
unmapped, and attempts to access it will generate faults.
If you specify memory for fake_start and fake_end, it should be present in
YOUR process. It need not be persistent. It is copied into the kernel and
allocated in the target process.
For clarity, you should probably page-align the cloaks yourself, since this is
how it works internally. Fakes need not be page aligned, as they are copied
into page aligned regions for you.
Normal process termination causes all cloaks to be removed. In some cases, a
process may exit without calling ZwTerminateProcess. For these cases, the
associated memory is freed if you unload and then reload Tron.
You need not probe or VirtualLock any memory. This is done for you. Cloaking
copy-on-write/"ProtoPTE" regions of DLLs is in fact supported.
NOTE: Code cloaking is only supported for pages that have 'ret' opcodes (both
0xC2 and 0xC3). Pages are scanned for automatically. Check DebugView for WRN
messages about pages missing rets. Rets need not be actual function rets.
Inserting random 0xC3 bytes is fine.
Also, code cloaking does not work in VMware due to improper iret
virtualization. Non-global ITLBs are flushed. DTLBs are fine.
2. REMOVE_CLOAK(pid, cloak_start, cloak_end)
Removes a hidden view, allocated fake memory, and all permissions associated
with that view.
3. ADD_ALLOWED(pid, code_start, code_end, cloak_start, cloak_end)
Adds permissions for the region of code to access the region of memory.
Permissions can be exact down to the byte for both code and cloaked region.
Permissions apply to the EIP range only. Unfortunately it is not possible to
have permissions apply to functions called from an allowed region. Walking the
stack from a page fault handler is not an easy task. Patches are welcome if
you discover a clean, fast, and safe way to do it. :)
4. REMOVE_ALLOWED(pid, code_start, code_end)
Removes a region of permissions. Does not subdivide regions.
5. HIDE_DLL_BY_NAME(pid, wchar_name, fake_start, fake_end)
Allows you to cloak a DLL and give it self-access permissions by name.
Removes DLL from process module list using WinXP offsets.
6. HIDE_DLL_BY_HANDLE(pid, dll_handle, fake_start, fake_end)
Same, but for a DLL handle. A DLL handle is the DLL's image base address, but
be aware that DLLs can be relocated, so its base in your process may not the
be same as its base in another process.
7. WRITE_HIDDEN(pid, dest, src, write_len)
Allows you to write to the hidden region of a memory page. Can go behind
'Null-Cloaks'.
8. READ_HIDDEN(pid, read, outbuf, len)
Same, but for read.
9. CHANGE_TRUST(pid)
Intra-thread race proofing call. Use before and after your hidden code
executes to guard against scanners running in your own thread. Resets TLBs by
writing to cr3.
10. PATCH_SCHEDULER(IDASwapContextAddress)
Patches the Windows scheduler to flush TLBs for every context switch. The
default behavior is to not flush for thread switches, which leaves us open to
scanners running on dedicated threads.
Give this function the address of SwapContext in IDA. The function adjusts
this address automatically for the real base address of ntoskrnl for that
boot.
Stacking Tron with ADHD
Tron CAN be stacked with ADHD. You should insert them as a stack, for example:
DrvrLdr -l infodisc.sys
DrvrLdr -l adhd.sys
DrvrLdr -u adhd.sys
DrvrLdr -u infodisc.sys
Failure to use LIFO order WILL cause BSOD. The ordering itself should not
matter so long as it is LIFO (ie like a stack).
Potential Working Set List BSOD (fixed?)
Believe it or not, in some cases the NT Kernel DOES verify that locked memory
is marked present in the page table. The function MiSwapWslEntries calls
MiCheckPdeForPagedPool and if it hits a Tron cloaked page, will raise a 1A
41289h BugCheck. The only case where this happened to me was via
VirtualFree. I believe I have prevented this from happening by hooking
ZwFreeVirtualMemory to mark all cloaked pages as present before the call and
unmarking them afterwords. It has not happened to me since this fix.
However, if you still notice this issue, there are a couple of things you can
do:
1. Nop that call to MiCheckPdeForPagedPool
2. Use SetupHotPatch() to have MiCheckPdeForPagedPool always return true,
or at least in cases of hooked pages.
3. Rewrite the pagefault handler to use the "supervisor" PTE bit a-la PAX
Option 3 will also require you invert all your PTEs so that the default PTE
for a page contains the fake address so that kernel calls will still get
fake views. Even then there is no guarantee this won't trigger some other
bugcheck somewhere else.
Though I do not promise continued support, reports and/or patches are
welcome. Please send mini-dumps if possible.
- Alan Bradley