Search This Blog

Tuesday, November 23, 2021

Trip down memory lane Part Deux



 Part 2, really?

I wasn't planning on doing this, but my bud Gareth asked me too, so, to please His Royal Sheepness, I'm totally doing this.

'Murica!


A bit after Fred abandoned us to live in California while still working for Borland, he reached out and asked me if I'd be interested in doing the same. I thought a bit about it, and decided that it would probably be a brilliant idea, but first, I would have to interview and get the job.

The job in question was to work in the Internal Team and be focused on Quattro Pro for Windows. I talked to a couple of people on the phone, and I guess that it was satisfactory enough because they asked me to go to Scotts Valley for about a week and have live interviews there.

In September 1993, I left from the Charles De Gaulle airport and landed successfully in SFO after stopping in Chicago for a bit. This was the very first time I ever took a plane, so I was kind of excited. Right before landing in Chicago, I looked at the window and saw the huge highway exchangers and I was thinking "Whoa, this is like in CHiPs! how neat!" (I tried to see if I could spot Ponch and the other dude, but to no avail).

Fred and Christophe came to the airport to pick me up at around 11PM or perhaps a little earlier. We got to Scotts Valley and since I was hungry, we stopped at Denny's before getting to Santa Cruz. So, yes, my first taste of American food was a chocolate milkshake.

Coming to America

I nailed the interview and got hired. So, at the end of February, I flew again for California. 

The first guy I met during my interview week, was Hidé(yuki). He and Fred became fast friends and I corresponded with Hidé via email a few times before leaving. 

A couple days after I arrived, Fred took me car shopping, because for one, I needed a car, and secondly, he loved haggling with the salesmen. Got me a 1990 Camaro RS and I guess that's when I really started to like American muscle cars.

Since I still had my rental car, we played around with it (don't do this at home, kids). Between the attempts at burnouts or just smashing the brakes while traveling 60 or so, we did have a ton of fun. The car, not so much.

I met a bunch of people and I'm still in contact with a couple. Hidé, Gareth (Baaaahhh) and Glynne were the ones I would hang out with. Sadly, Glynne passed away a little while after going back to England (cancer sucks).

Fred and the other French peeps went back to France. Fortunately, Hidé and Gareth are still here.

Brits and Trips

Aside from a very few American people, we would mostly hang with guys from the International team.
I met Gareth at Feast Eddie's where we used to play pool. My English at the time sucked, but at least I could understand most people.

Fred told me: "Gareth is going to join us", and I was like, ok, cool.
In comes the Welshman, we said hi and then he talked to me for a couple of minutes. At the end of what I would characterize as a monologue, I turned to Fred and told him: "Dude, I have no idea what he just said, not. a. single. word!". The ever so magnanimous Fred translated for me.

To be frank, it was not just me that could not comprehend the man. Fred, Glynne, Gareth and I made a trip to Los Angeles to visit, and in the morning, we went to a donut shop to have breakfast and Gareth ordered a raspberry filled donut. The dude at the counter had no idea what G was talking about, so Fred had to order the jam filled delicacy. Kind of ironic that a Frenchman has to order for a Brit, really.

We did some more trips, including going to Tahoe on Labor Day week-end. We shared driving between Fred and I, and I drove most of the way back. I can't remember if we were on our way back, but I got stopped by the CHP for speeding. The officer came to my window and said I was speeding. He asked if I knew how fast I was going, and I was like, hmmm, don't know... 
He pointed to the speedometer, and said that I was going faster than the max speed indicated on there (80MPH I believe it was). I think I was doing close to 100MPH. I feigned ignorance, and gave him my French driver license. He came back was told me to slow down and beware of drunk drivers. 

I looked out for drunk peeps, but I didn't really heed his warning about the speed limit. The fact that Glynne was extra white after me driving the mountain road between San Jose and Scott Valley was a clear indication that I felt like Ayrton Senna or something.

Life at Borland

Those were a cool couple of years. Met a ton of people there, mostly Europeans and an American  named Ken. Dude was hilarious and Fred would teach him all sorts of swear words. Good times.

That building was fantastic, the developers were the elite of the company, so we were seating on the top floor, in single offices, no cubes, nobody to bug you or anything, just you in a nice office with a door. 
The other scrubs, namely QA and Tech Support were on the second floor because that's all they deserve, sorry Gareth. No elitism there, none whatsoever.

Borland was a great place to work. We had to crappy PCs to work with (they were pretty awesome at the time actually). I don't remember if they were Dell or something, but some had some 286 and some had 386. The 286 guys got the short end of the stick for sure. Those processors were horrendous, clearly not Intel's finest hour.

Sometimes we had those LAN parties and we'd play Descent at lunch time. Epic stuff.

My life at Borland was almost very brief. 
I started at the end of February, and around May my manager asked me to come to his office. He announced that Novell had acquired Quattro Pro for Windows, which was the product I was working on, and, since I was on a L1 visa and those are not transferable between companies, I was gonna get terminated and would have 14 days to find another job at Borland or, get shipped back to France, or become an illegal alien or something. Then he added: "Don't fret yo! we'll take care of your plane ticket" (pretty sure he didn't say it like that, but I think it sounds 200% better).

I went around, asked if the Pascal or C++ compiler team needed a dev, alas, no bueno. I was getting a little worried, and that's when Martin Levy (yet another Englishman) pretty much saved my bacon. It was the I18N team pretty much and Christophe Job, who had moved from the French office got a job in one of the compiler team (that was my dream job in fact). 

Martin needed a guy, and he offered me the job, which I promptly accepted. It was a great couple of years working with him, great guy.

A few month later, the great French peeps exodus happened, and I found myself surrounded by Swedes, Danish, Germans, Brits and whatever else. I would still hang out with Hidé and Gareth though, which was fun. 

I played a few games of squash with Gareth, but he was clearly better than me, and it was too dangerous for me because I would hit the walls pretty hard. Too much running anyway, and I don't like to run. 

With Hidé we went surfing a couple of times, love the guy despite the fact that he almost murdered me with his surfboard once. It was just a freak accident, so no problem, we cool.

Life after Borland

After a couple of years at the company, things got kinda bad. Phillipe (the CEO) left, the company made a series of bad choices (like acquiring Ashton Tate: DBase), or going at war with Microsoft. There were layoffs etc, and since I had recently got my green card (yay for the lottery!) I decided to move. 

I interviewed at Netscape, and Pointcast. Both gave me an offer, but I ended up picking Pointcast. Needless to say, it wasn't the best decision ever. I had fun there, and Gareth actually joined shortly after me. At least I had some familiar face with me, and we were able to carpool. 

One cool thing was that the office was right next to the golf course by Maude and 237 in Sunnyvale. So, on Tuesday, we would discreetly leave the office in the afternoon and do the twilight thing ($17 to do the full course). I don't think we ever completed the whole 18 holes because it gets dark so early around here, and we lost a lot of balls because we could not find them in the dark. We also lost a boatload of balls in the  ponds, etc... We bought some golf clubs set at Costco, a regular set for me and a weird one for G, since he's a southpaw. 

I have been commuting over 17 ever since. Then again, not like there are a ton of IT companies in the area. Pines, Strawberries, artichokes, mountain lions and skunks: yes, IT and Sasquatches: no. Especially sad that there are no Squatches around here.

Time flies...

Tuesday, October 26, 2021

Trip down memory lane

 I've been meaning to blog recently, but I haven't had much time to do so, and I also have to pick some interesting subject.

Since I couldn't come up with anything interesting for the time being, and because I can't even blog about taking my car to the track since I sold both my Challenger 392 and my Viper ACR (Insert super sad face here), I figured that I would take a trip down memory lane.

Building cabinets, not software

I wasn't even supposed to be in this line of work. 

Originally, when I was about 14 or so, all I wanted to do was wood working, you know, like building cabinets, set of drawers etc. Cool stuff and I wasn't half bad with a chisel. 

At the same time, my father helped me buy a Casio FP-200 which was pretty cool.

I started doing some programs in Basic and I got more and more interested in it. Between that and my mom telling me that working with wood is great, but that I would end up fingerless after a couple of years, I decided that I would pursue a career doing  'geeky computer stuff'.

Fast forward to when I got hired by Borland Intl. as a tech support. 

Doing geeky stuff

That was the place where I met Fred and Christophe. Those two were working in the Localization Team and we quickly became friends, especially since we all had the same interests. Well, okay so, we were kind of geeky.

We started to write a bunch of different programs for MS-DOS at the time. Most of the time, we'd use Turbo Pascal to do so, but we moved on to x86 Assembly because that was rad! Plus, real programmers code with Assembly, that's a well known fact.

At that point we wrote a "demo", which was a small program written in Assembly and that had some CGA animations. Fred made some super cool molecule looking thing that was spinning, I made a lame ass chessboard that was scrolling infinitely with some mountains on top that were rotating from right to left (if you fail to understand the relationship between a chessboard and a bunch of mountains, you're not the only ones). Pretty sure there were a couple more animations in there, but I can't remember what they were. 

Christophe got the music, and I have no idea how he digitized it, but I got a file and I programmed the SoundBlaster to play it. 


Yes, that really is a 3.5" disk... it even says 1992-1993. I actually have two of those puppies.

I used a filter to make it look even cooler! Rad even!

I know what you are wondering, what the heck does DP stand for? 

DP means Dark Priests. Right, so at the time we thought it was cool, and didn't realize how corny/cheesy/lame that was. Especially considering that none of us has a religious bone in their body...

Lord of the Rings and Hacking/Cracking

At first, you may wonder how LOTR and Hacking are related, right?
Well, they are not. It's just that Fred is a big fan of that book, and I wouldn't say that he forced me to read it, but after much reticence, I did.

I thought it was alright, but not really my cup of tea. Don't get me wrong, it's a good book, but I just couldn't really get into it. The hobbits are wimps and can't do crap, the humans and the orcs are dumb, and the dwarves are, well, dwarves, and the elves are a bunch of hippies with bows. I actually liked the dwarves, especially Gimli.

As we started doing stuff like writing computer viruses that didn't do anything bad (we were in it for the challenge of making undetectable stuff), cracking video games' protection, we decided to adopt some persona/avatar, so that if/when we would release the cracks, we'd used those names as the authors of such and such crack. 

I was Gimli and Fred was the wimpy Frodo. Christophe, because of his advanced age (he's one year older than Fred and I) was much more serious and wiser, so he didn't really crack games, or at least not that I can remember of.

I don't think any of those hacks made it any further than Fred's living room. Again, we were just looking for the challenge. It took me two days to crack a game I didn't even play, although Fred did if I remember correctly. I must admit that I was quite proud of myself. The hack was not a simple op-code replacement in the binary, I had to do it while the program was running, so in-memory patching.

(I still think that was cool)

Tetrix for Béatrix

Before moving out, another member of the Localization Team and myself made a bet. That person was Béatrix, and I used to tease her all the time. At the time, she was working on Paradox for Windows, which was the competitor to DBase from Ashton Tate, which Borland acquired later for some messed up reason.

Anyway, Paradox had a scripting language named ObjectPAL. I knew nothing about it, but I kept on telling Béa that it was super easy, etc. So, she challenged me and I told her that I would write a game of Tetris for her using that stuff, and I would do it in a week. Conceited much?

That week, I was half answering customer calls because I was busy reading the documentation for ObjectPAL. When Friday came, I had a working Tetris and I gave that to Béa, who, the very next Monday brought me a big box of chocolates. Sadly, my dog snatched the box and hate most of them (yes! he undeservingly survived).

Moving to California

In 1993 Fred moved to California and I followed him a few months later. We was super serious at the time, so no hacking or anything. We still had LAN parties during lunch time at work though.

I had a lot of time on my hands, so I started writing more programs for MS-DOS and eventually for Windows 3.1.

The last project I did on MS-DOS was an editor named TED. I have no idea why I named that thing TED, but I think it was an acronym for Turbo Editor & Debugger (maybe). I used Turbo Pascal with the Turbo Vision framework. It was an editor for Turbo Assembler.

That program had everything, like: syntax highlighting, options for everything, could compile your code and debug it. Had to play around with INT 1 and INT 3 for the debugging code.
It even had a shell exit so that you could run the MS-DOS CLI while the editor was still there and you had just about the full 640K usable memory too (was saving the runtime on disk). 

Some guy from NY actually sent me $50 for it, even though I had posted it as Freeware. That was pretty nice of him.

What now?

A bit over 20 years later, I'm still in California, while most of the other French people I met here went back. Not too sure what they're all up to beside for Fred who's a CTO as a Service

I'm still doing side projects whenever I have some time to spare. A project that I started back in the late 90s was an Operating System. I'm still working on it even though I had a many years hiatus. About 4 years ago, I thought, why not give that a try again? So I did, Dusted off my i386 books and got back at it.

That thing boots but that's it. I run it via QEMU on Debian, and debug it with GDB, which works pretty well. I learned a lot about Linux while resuming that project. 
I just wish I had more time, alas, it's not the case so it'll go on the back burner once again.

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.

Friday, August 7, 2015

MongoDB and AWS Lambda

I haven't posted a blog in quite a while since I've been busy at work (new job) and outside of work.
I've been working on an app with my buddy and we decided to use PhoneGap to write it (well, I'm writing the backend and the JS scripts while he takes care of the GUI).

Anyway, I've also decided to use AWS to do the whole backend. I still have to have a simple EC2 instance to run some job on regular basis but otherwise, everything is handled on AWS.

I am taking advantage of the Lambda service because I can write code there instead of inside the app, which means that whenever something needs to be changed, the app doesn't need to be updated (or at least not as often).

Initially I was using Lambda to query my DynamoDB instance.
Since DynamoDB is quite expensive, in case it gets too pricey, I will switch to MongoDB (could have picked Cassandra but I like Mongo's name better...).

I wasn't sure as how to access Mongo from Lambda but I figured it out.

First, I created a Bitnami instance with MongoDB. That's pretty cool because it's available to AWS Free Tier and it's pre-installed so you don't have to do diddly squat or almost.

You need to configure Mongo so that it allows traffic other than 127.0.0.1.

Edit the config file:

sudo vi /opt/bitnami/mongodb/mongodb.conf

Comment out that line:

#bind_ip = 127.0.0.1

You also need to allow the port with the local firewall:

sudo ufw allow 27017

Restart Mongo:

sudo /opt/bitnami/ctlscript.sh restart mongodb

You're almost good to go. The last thing is to allow the port on the AWS console via security group.
Find out which security group is your EC2 instance using and add the 27017 port in the Inbound section.

Now, you can query Mongo from everywhere. Probably not the best security posture but eventually you can limit the access from a specific IP.

Before doing anything else, you need to install the Mongo driver via NodeJS onto your development machine:

npm install mongodb

You will have a new directory named "node_modules" should look like this (minus the index.js and .zip)


You can write your NodeJS script and create a zip file. The script has to be named index.js.
Here's a small sample:

var mongodb = require('mongodb');

console.log('Loading function');

exports.handler = function(event, context) {
    console.log("Connecting to Mongo");

    mongodb.MongoClient.connect('mongodb://user:password@ec2-blah.compute-X.amazonaws.com:27017/database', function(err, db) {
        console.log("Connected to mongo");
        var col = db.collection('Users');

        col.find({ userID: "415173559090" } ).toArray(function(err, docs) {
            if (err) throw err;
            docs.forEach(function(doc) {
                console.log(doc);
            });
            
            db.close();
            console.log("Done");
            context.done(null, "finished");
        });    
    });
};

Upload to Lambda, test, happiness!

Your Lambda function should have at least 512Mb of memory, and 1024 is better. The more memory, the faster it will connect to your mongo instance.

That little sample takes 1600ms with 1024Mb and 3800ms with 512Mb.

Thursday, October 9, 2014

API hooking without DLL injection

Lately I have been working on some project to do API hooking with minimal disturbance of the target programs.

I've tried a bunch of things but the reality is that there is no two way around it, you have to inject a DLL and you have to either modify the import table or do preamble patching.

While both methods do work, it is trivial to detect IAT patching and preamble hooking can be defeated with hook hopping or just by checking if a DLL does or does not belong to your process; of course you can attempt to hide your DLL by removing the entries in the 3 linked lists in the PEB (4 if you include the Hash list) but your binary will still be visible via a QueryVirtualMemory() call. This is quite complicated work just to hide yourself. Not to mention that you still have to hook some DLLmain

Also, there are issues with injecting any sort of foreign module into an application. One is that you need to use your own memory manager other you may mess up the heap of the target. Some malware will unload the main program, resize the memory where it was loaded and reload it, unpacked and this will cause the program to crash if your DLL has already done some allocation which has been placed right after the loaded module (memory can't be resized to anything bigger than it was and the call will return NULL. The unpacker will not check for the the NULL pointer and crash).

There was some research done by some people at Purdue regarding instrumenting and debugging via Hardware Virtualization (ttps://www.cerias.purdue.edu/assets/pdf/bibtex_archive/2013-5.pdf) but  I had something a little different in mind.

What about the use of little known MSR?

I was made aware of a feature that exists on both AMD and Intel which could potentially solve my problem. On those CPU, there is a specific set of MSRs that allow to do some profiling. One MSR that sounded very interesting was the DebugCTL MSR. There are another that allow you to get a list of the last 16 branches that occurred on a CPU and there are a few more that give you information about the last branch record (giving you source and destination of the last branch).

The basic idea is to take advantage of the Debug Control MSR.
What it does is that once you've set up the proper flags (bit 0 and 1):


mov ecx, 0x1d9 ; DebugCTL_MSRrdmsr
or eax, 0x3
wrmsr
xor eax, eax
rdmsr          ; Just to make sure it worked.
Now if you run this code on VMWare, the last rdmsr with return 0 in EAX because that MSR is ignored. In order to get this to work, you would have to use some KVM based VM or possibly XEN but I haven't had the opportunity to try with XEN.

Now that the MSR is set up, for each thread that has the Trap Flag (TF = EFlags bit 9) a INT 1 will be generated for every branching instruction such as CALL, JMP, JZ, RET, SYSCALL, Etc...

I wrote two pieces of code to handle this.

Handling the DebugCTL_MSR inside the guest (or physical machine)

The first thing I did was to write a INT 1 handler. It's quite small (and incomplete) and goes something like this:


pushad         ; Save all registers
push fs
push ds
push es
mov bx, 30h
mov fs, bx     ; Set FS to 30h since we're in the kernel
mov bx, 23h
mov es, bx
mov ds, bx     ; ES and DS are now set the 23h

mov ecx, 1d9h  ; Branch to address MSR
rdmsr
push eax

mov ecx, 1dch  ; Branch from address
rdmsr 

mov bl, byte ptr [eax] ; Retrieve the op-code at EAX
pop eax        ; restore EAX with Branch to address

cmp bl, 0e8h
je JmpOrCall
cmp bl, 0e9h
je JmpOrCall
cmp bl, 0xFF
je JmpOrCall
jmp short NoRange

JmpOrCall: 

push eax
call HandleSingleStep

NoRange:

mov ecx, 1d9h
xor edx, edx
mov eax, 3
wrmsr          ; Reset the MSR value 

...
Quite rudimentary but it works.

There is a small optimization here where it checks the op-code of the instruction where the branch was made. It checks that only a JMP, CALL or FAR CALL has been made. We don't really care about the conditional jumps or anything like this.

The driver that contains the INT 1 handler also does a few more things. It still injects a DLL (because that was the fastest thing for me to do) and retrieves the addresses of a few hooks. Then, when Kernel32.DLL gets loaded, it retrieves the addresses of the target API (for instance: CreateFileA).

The HandleSingleStep(DWORD callee) will then resolve the address in the sense that it will check if the branch to address matches any of the APIs that we want to hook.  Once a match is found, all we need to do is to get the matching hook's address and change the return address of the INT 1.


Above is the flow of operations (or was since the picture is gone AWOL...).

The reason for me to still inject a DLL was to demonstrate that I could print some log in the hook and then resume the operations. Of course, the beginning of hookedCreateFileA() requires resetting the TF so that we can call the original CreateFileA() and then set TF again. Otherwise, we encounter the risk of getting into some deadlock.

Everything should be done inside the kernel driver. Since the INT 1 runs in the context of the application, we can access memory rather easily and do all sorts of things from there.
There is no need to have an extra DLL which in fact defeats the purpose of the solution.

The biggest problem is performances. If you think about it, every time that a branch is made, an INT 1 is getting triggered. Which means context switch a-gogo and time wasting left and right.

Also, and equally important is the fact that this only work on Windows XP. The reason for it is that NtCreateThreadEx() isn't called by NtCreateProcess(), instead Windows makes use of some private function (PsInsertThread). Since it's private, it would be harder to hook.

We need to hook the thread creation function to force TF to be set to 1. The easier is to change the PCONTEXT at thread creation time. I tried with using some Kernel APC triggered when the thread was created but unfortunately, the KTRAP_FRAME structure in EPROCESS is not yet valid. It isn't available during Thread Resume operation either...

The other issue that we face is with Windows x64. Patch guard will prevent us from hooking INT 1 and NtCreateThreadEx() unless we get rid of it, which may or may not be an option.

How about doing this on the host (for a VM)

I did that too.
It works well and is much easier to implement than inside the guest. Basically, we can setup TF when CR3 is written into (VMExit) and intercept the INT 1 when it pops.

Performance here is a much bigger issue because for one, every time the INT 1 is intercepted, we have a VMExit which is very costly. Unless we can do the filtering there (ignoring conditional jumps and whatnot) this causes a lot of unnecessary noise.

Another big problem is that when the program we monitor makes a SYSENTER/SYSCALL, TF is reset and it needs to be set again at SYSEXIT. If we do a VMExit per SYSEXIT, the performances go down drastically (VMExit requires a lot of CPU cycles and then the user mode app still needs to be scheduled to run).

What then?

I still believe that the use for this can be very good but would have to be done in a sporadic manner. For instance, do regular hooking unless a program is twitchy enough that we ought to use something less invasive.