Apexes and System Calls
Search This Blog
Tuesday, November 23, 2021
Trip down memory lane Part Deux
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
Tetrix for Béatrix
Moving to California
What now?
Wednesday, November 23, 2016
Using APCs to inject your DLL, reloaded
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
NTSYSAPI
NTSTATUS
NTAPI
LdrLoadDll(
IN PWCHAR PathToFile OPTIONAL,
IN ULONG Flags OPTIONAL,
IN PUNICODE_STRING ModuleFileName,
OUT PHANDLE ModuleHandle );
Injection of a 32bit DLL from a 64bit Kernel
32Bit shell code
Friday, February 19, 2016
How to control your Android phone which has a broken screen
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
Python to the rescue
#!/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 '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:
What's next?
Thursday, February 18, 2016
Running Opensuse (Tumbleweed) on a Dell XPS 13
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
Preparing Linux for compiling the source
~ 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
~ 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
# rmmod brcmsmac
# rmmod ssb
# rmmod bcma
# rmmod wl
# echo "blacklist bcma" >> /etc/modprobe.d/blacklist.conf
# echo "blacklist b43" >> /etc/modprobe.d/blacklist.conf
# echo "blacklist brcmsmac" >> /etc/modprobe.d/blacklist.conf
Manager to notice a new network driver has been installed and show the
surrounding wireless networks.
Friday, August 7, 2015
MongoDB and AWS Lambda
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
What about the use of little known MSR?
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)
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 ...
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.
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.