# 17. Internals

Because some horrible hacks of `PythonForWindows` are hidden and I wanted to talk about it.

## 17.1. remotectypes.py

Performing parsing of PEB / PE in remote process may be painful and i didn’t want to have two versions of all my parsing code.

So I made a wrapper around `ctypes` that is able to do two things:

> - Transform a 32bits ctypes structure into a 64bits one and reverse

> This is done by replacing the `c_void_p`/`c_char_p` by `DWORD` or `QWORD` and rewriting a wrapper around the `ctypes` `POINTER` and other stuff. It might not works for every structure by i didn’t have any problem for now.

> - Read the memory in another process

> For this one I rewrote a class that use the standard `ctypes` structure offset-size calculation, extracts those information when asked for a field and read it from the target process. We just need to take care of special cases: `POINTER` / `ARRAY` / `STRING` / ..

We also need to be carreful about the inheritance, we need to inherit from “hidden” `ctypes` classes to keep the magic working.

This module exports the following API:

`windows.remotectypes.``transform_type_to_remote32bits`(ftype)

`windows.remotectypes.``transform_type_to_remote64bits`(ftype)

Both functions return a class that represent the structure in a remote process. The class.__init__ accept two arguments:

> - `base_addr`: the address of the object in the remote process
> - `target`: an object with a method `read_memory` (so a `windows.winobject.WinProcess` in our case)

Example `WinProcess.peb`:

    def peb(self):
        if windows.current_process.bitness == 32 and self.bitness == 64:
            return RemotePEB64(self.peb_addr, self)
        if windows.current_process.bitness == 64 and self.bitness == 32:
            return RemotePEB32(self.peb_addr, self)
        return RemotePEB(self.peb_addr, self)

I am pretty sure that this code does NOT handle all the cases, so it might break some day.

## 17.2. syswow64.py – Crossing the heaven gate

One of my goal with `PythonForWindows` is to have some abstraction of the bitness of the processes. It means being able to work on a `32bits Python` or a `64bits Python`.

In the case of a 32bits python on a `64bits` system (`SysWow64`) it’s not trivial to perform operation on other `64bits` processes. For example directly calling `CreateRemoteThread()` will not work.

To be able to perform those operation we must be able to execute code in the `64bits` part of our `SysWow64` process.

Note

See Knockin’ on Heaven’s Gate – Dynamic Processor Mode Switching

For that we need to jump to the 64bits segment of our process, execute some code then return. To do so, we need to use some `far jump` / `far ret` with the segments selector `0x23` (CS_32bits) and `0x33` (CS_64bits).

The generation of this is quite ugly in my case. This code is in:

`windows.syswow64.``execute_64bits_code_from_syswow`()

Once we are able to execute some code in the `64bits` part we need to create the code that will call our API (in NTDLL). To do that, I rely on the type information already present in the function of `windows.winproxy`. With these information we are able to know

> - The name of the API
> - The number of arguments

Then I generate the correct x64 stub (using `windows.native_exec.simple_x64`) with the function:

`windows.syswow64.``generate_syswow64_call`()

One problem I encountered is that our function must be able to pass values of 64bits, so passing arguments by register is not possible.

For now I allocate a buffer where a python wrapper copy the parameters and the x64 stub retrieves them from here.

(It might be possible to do something by creating a WINCFUNC with only ULONG64 parameters).

`windows.syswow64.``try_generate_stub_target`()

The final result is a `Python` function like the one in `windows.winproxy`

> - It copies the arguments in the buffer
> - Jumps on the 32->64 stub
> - X64 bits code retrieves the arguments in the buffer and setup the registers and the stack for the call
> - Calls the API
> - Returns to 32bits mode.

class `windows.syswow64.``Syswow64ApiProxy`

Existing function are:

`windows.syswow64.``NtCreateThreadEx_32_to_64`()

`windows.syswow64.``NtQueryInformationProcess_32_to_64`()

`windows.syswow64.``NtQueryInformationThread_32_to_64`()

`windows.syswow64.``NtQueryVirtualMemory_32_to_64`()

`windows.syswow64.``NtGetContextThread_32_to_64`()

`windows.syswow64.``NtSetContextThread_32_to_64`()

`windows.syswow64.``LdrLoadDll_32_to_64`()