Search This Blog

Wednesday, November 23, 2016

Using APCs to inject your DLL, reloaded

In a previous post Using APCs to inject you DLL I talked about injecting a DLL from the Windows Kernel.

Since the post was lacking some details, I decided to add a couple things and also talk about how to inject a 32bit process from a 64bit kernel.

When to inject our DLL

For a 64bit process, I usually do it right after ntdll.dll has been loaded. You can do this easily when you get a module load notification. You can get the notification by making a call to PsSetLoadImageNotifyRoutine().

The reason to wait for ntdll.dll is that once it is loaded, we can get the address of LdrLoadDll()

NTSYSAPI 
NTSTATUS
NTAPI

LdrLoadDll(
  IN PWCHAR               PathToFile OPTIONAL,
  IN ULONG                Flags OPTIONAL,
  IN PUNICODE_STRING      ModuleFileName,
  OUT PHANDLE             ModuleHandle );

When using LdrLoadDll() you should end up with code like this:

void NTAPI ApcLoadDLL(LPLDR_CONTEXT ctx, PVOID  SystemArgument1, 
                      VOID SystemArgument2) {
    UNREFERENCED_PARAMETER(SystemArgument1);
    UNREFERENCED_PARAMETER(SystemArgument2);
    HANDLE Module = NULL;

    ctx->LdrLoadDll(NULL, 0, &ctx->dllPath, &Module);
    return;
}

The context being defined as such:

typedef NTSTATUS(*LDR_LOAD_DLL_FN)(
    IN PWCHAR               PathToFile OPTIONAL,
    IN ULONG                Flags OPTIONAL,
    IN PUNICODE_STRING      ModuleFileName,
    OUT PHANDLE             ModuleHandle);

typedef struct ldrContext {
    PVOID ShellCode;
    UNICODE_STRING dllPath;
    HANDLE Process;
    LDR_LOAD_DLL_FN LdrLoadDll;
} LDR_CONTEXT, *LPLDR_CONTEXT;

The dllPath of the context is just a PUNICODE_STRING that contains the path of the DLL we want to inject.
That function will work as 64bit shellcode but for 32bit we'll need something different and basically 32bit assembly.

Injection of a 32bit DLL from a 64bit Kernel


The first thing that changes is when we inject the DLL. For 64bit we wait for ntdll.dll to be loaded (conveniently, it just happens to be the very first library loaded) but for 32bit APC we need to wait for a different library: wow64.dll

The reason for this is that to use an APC in a 32bit process, you can't just give the address of the routing that you want to execute. You need to give the address a specific API that is inside wow64.dll. Basically it's a thunking mechanism. 

The function that will do the work is: Wow64ApcRoutine

That function will be your APC routine, which in turn will call your actual shellcode.
The Wow64ApcRoutine routine is an APC normal routine. 

The parameters given to it are very specific though. When you create your APC you should have something like this:

LPLDR_CONTEXT32 context = (LPLDR_CONTEXT32)ctx;
PVOID ApcContext = (PVOID)(((ULONG_PTR)Apc32BitRoutine  << 32) + (ULONG_PTR) Apc32BitContext);
KeInitializeApc(apc, tThread,
OriginalApcEnvironment,
(PKKERNEL_ROUTINE)&KernelApcRoutine,
NULL,
context->Wow64ApcRoutine,
UserMode,
ApcContext);

KeInsertQueueApc(apc, 0, NULL, 0);

The context and other structures being defined as such:

typedef union
{
    struct
    {
ULONG Apc32BitContext;
ULONG Apc32BitRoutine;
    };
    PVOID Apc64BitContext;
} wow64ApcContext;

typedef wow64ApcContext  WOW64_CONTEXT;
typedef wow64ApcContext* LPWOW64_CONTEXT;

typedef struct ldrContext32 {
    ULONG ShellCode;
    UNICODE_STRING32 dllPath;
    DWORD Process;
    DWORD LdrLoadDll;
    PKNORMAL_ROUTINE Wow64ApcRoutine;
    WOW64_CONTEXT wow64Context;
} LDR_CONTEXT32, *LPLDR_CONTEXT32;

The Apc32BitRoutine is the address of your shellcode (you will have used ZwAllocateMemory() for the target process earlier).
The Apc32BitContext is your structure (basically just need the PUNICODE_STRING that specifies the path of your DLL)

The APC will therefore call Wow64ApcRoutine (you got the address of that after wow64.dll got loaded), and in turn, it will call your shellcode with the given context as a parameter.

32Bit shell code


In an earlier iteration, I used the following code:

UCHAR x86shellCode[] = {
//"\xcc" // Break Point
"\x55" // push ebp
"\x8b\xec" // mov ebp, esp
"\x8b\x45\x08" // mov eax, dword ptr [ebp+8]
"\x83\xc0\x0c" // add eax,0Ch
"\x8b\xf4" // mov esi,esp
"\x50" // push eax
"\x8b\x4d\x08" // mov ecx, dword ptr[ebp+08]
"\x83\xc1\x04" // add ecx, 4
"\x51" // push ecx
"\x6a\x00" // push 0
"\x6a\x00" // push 0
"\x8b\x55\x08" // mov edx, dword [ebp+8]
"\x8b\x42\x10" // mov eax, dword [edx+8]
"\xff\xd0" // call eax Note: No need to clean the stack after the call
"\x5d" // pop ebp
"\xc3" // ret
"\x90\x90\x90" // NOP
};

This will get the address of LdrLoadDll from the context as well as the UNICODE_STRING with the path. Essentially it does the exact same thing as the 64bit code mentioned at the beginning.


Friday, February 19, 2016

How to control your Android phone which has a broken screen

Who hasn't dropped their phone?

Well, alright, maybe some people never do but I'm not one of them.
I dropped mine a couple days ago and since then, the screen doesn't respond to touch.



I figured that that was it but while I'm waiting for my new phone to be delivered, I wanted to be able to still use the device.

Fortunately, since I am doing development on the phone, I have it set up for it. Only problem is that only my home desktop machine is authorized to access the phone via ADB. Bummer but it's still a good thing.

What do you need?


  • USB cable
  • Android SDK and more specifically adb
  • Python (to make things a little easier)

Connecting to the phone


I'm using Linux at home so the first thing is to do something like:

~ sudo ~/Android/Sdk/platform-tools/adb devices

This will start the adb daemon and you will be connected to the phone.
You can then use adb with your user account normally. We use sudo here to start the daemon and avoid authorization issues.

ADB provides a shell that you can use to do a lot of things:

~ adb shell
xx@mako> pull /sdata/DCIM/Camera 

Will copy the files inside /sdata/DCIM/Camera onto the hard disk of the computer (in the current directory).

~ adb shell input tap 100 100

This will instruct the phone to do a tap at the given coordinates.

Python to the rescue


I wrote a small python script to do a bunch of actions because typing adb shell input tap xx xx becomes rather annoying after a while.

It goes like this:

#!/usr/bin/python

import subprocess

alive = True

while (alive):
    isCommand = False

    text = raw_input(">")
    if text == "send":
        isCommand = True
        subprocess.check_call("adb shell input tap 700 1150", shell=True)
        print "sent"

    if text == "sup":
        isCommand = True
        subprocess.check_call("adb shell input swipe 300 900 300 100", shell=True)

    if text.startswith("tap"):
        isCommand = True
        coords = text.split()
        subprocess.check_call("adb shell input tap " + coords[1] + " " + coords[2], shell=True)

    if text == "shownotif":
        isCommand = True
        subprocess.check_call("adb shell input swipe 400 10 400 1000", shell=True)

    if text == "unlock":
        isCommand = True
        subprocess.check_call("adb shell input swipe 400 1150 400 200", shell=True)
        subprocess.check_call("adb shell input text 0000", shell=True)
        subprocess.check_call("adb shell input keyevent 66", shell=True)

    if text == "home":
        isCommand = True
        subprocess.check_call("adb shell input keyevent 3", shell=True)

    if text == "end":
        isCommand = True
        alive = False

    if text == "enter":
        isCommand = True
        subprocess.check_call("adb shell input keyevent 66", shell=True)

    if text == "back":
        isCommand = True
        subprocess.check_call("adb shell input keyevent 4", shell=True)

    if isCommand == False:
        text = "\"" + text.replace(" ", "%s") + "\""
        subprocess.check_call(["adb", "shell", "input", "text", text])

Things to change


The script works well on my phone, which is a Nexus 4.

First thing to modify is the unlocking code: subprocess.check_call("adb shell input text 0000", shell=True)
For this line, replace the 0000 with your personal PIN

The 'send' command will also need to be changed to use the proper coordinates.
On my screen the WhatApp or Viber send buttons are bottom right, which is around 700,1150.

Your phone will most likely be different depending on the screen size and DPI.

Commands:


send: Send the message
back: Back button
home: Goes to the home screen
enter: Enter button (for example after entering the PIN, [enter] will unlock the phone)
sup: swipe up (from bottom to top, here again you may need to change the numbers)
tap: taps at the given coordinates (example: tap 400 400)
unlock: Unlocks the phone with the hard coded PIN
shownotif: will show the notification list (swipe from the top to the bottom of the screen)

What's next?


You can also run apps with adb: 

adb shell am start com.whatsapp/.Main

This will launch the WhatsApp app.

After that, by using swipe, tap and whatever else, you can still use your phone and download files from it while you wait for your new device to appear at the front door.
Basically just experiment (I archived my notes from Google Keep using adb) and have fun.

Thursday, February 18, 2016

Running Opensuse (Tumbleweed) on a Dell XPS 13

I don't have a XPS 13 but I do have a XPS 15.

Installing Opensuse on it was not too hard really but my friend does have a 13" and the biggest problem is that the Wireless card won't work.

The problem is that the drivers included on Opensuse don't work with the Broadcomm 4352 that's on the machine.

The are some pre-requisites to make this work:
  • You need another machine with Opensuse and the same kernel (or at least, close enough)
  • You need to get the source RPM for the broadcom 43xx cards
  • You need the kernel source and what not (gcc, kernel-devel, etc)

Getting the driver source

You can get that RPM Here: Packman mirror

The file should be around 2.9MB

Preparing Linux for compiling the source

~ sudo zypper install kernel-devel
~ sudo zypper install kernel-headers
~ sudo zypper install gcc

Make sure that the kernel source are for the kernel you have on the machine.

~ uname -a
Linux linux-c0wc 4.4.0-3-default #1 SMP PREEMPT Thu Jan 28 08:15:06 UTC 2016 (9f68b90) x86_64 x86_64 x86_64 GNU/Linux

~ ll /usr/src

You should have a directory here named: linux-4.4.0-3

Extract the source RPM:

~ rpm -ivh broadcom-wl-6.30.223.248-6.31.src.rpm

Apply the patches

~ cd ~/rpmbuild/SOURCES/
~ mkdir hybrid_wl
~ cd hybrid_wl
~ tar -xzf ../hybrid-v35_64-nodebug-pcoem-6_30_223_248.tar.gz
~ patch -p1 < ../broadcom-wl-4.2.patch
~ patch -p1 < ../broadcom-wl-6_30_223_248-disable-timestamps.patch
~ patch -p1 < ../broadcom-wl-6_30_223_248-linux-4.x.patch

Build it

~ make

 You should end up with a result like this:



Copy the wl.ko onto your trusty USB stick and mount it onto the XPS 13.

Then, install the driver according to the broadcomm document (here)

I'm copying parts of it here to make it a little simpler.

~ sudo su

# lsmod | grep "brcmsmac\|b43\|ssb\|bcma\|wl"
If any of these are installed, remove them:
# rmmod b43
# rmmod brcmsmac
# rmmod ssb
# rmmod bcma
# rmmod wl
To blacklist these drivers and prevent them from loading in the future: (this step is important since after reboot, if you haven't done this, the original modules will be loaded and your WiFi still won't work)
# echo "blacklist ssb" >> /etc/modprobe.d/blacklist.conf
# echo "blacklist bcma" >> /etc/modprobe.d/blacklist.conf
# echo "blacklist b43" >> /etc/modprobe.d/blacklist.conf
# echo "blacklist brcmsmac" >> /etc/modprobe.d/blacklist.conf
Insmod the driver.

# insmod wl.ko

wl.ko is now operational. It may take several seconds for the Network
Manager to notice a new network driver has been installed and show the
surrounding wireless networks.

You can also reboot and once you launch the Network Manager, you should see the different networks.