Interfacing with encrypted android API’s using node.js

Memphis-Beale-Street-horse-and-carriage-ride

I would only travel by horse if I had a choice – Linda McCartney

In today’s more than ever competitive APP market, some developers are turning to more clever means in order to make a pay check.  Take for example albion-services.com. They are a small tech company in Olympia Washington that makes a profit by interfacing with Tinder’s public facing API and providing user searches. Why make the next great dating app when you can make money off what has already been done?

The only problem with this philosophy is that all APP developers aren’t as lazy as the Match group who makes Tinder. Many apps today are using custom application layer encryption for their API’s on top of existing SSL certificates. You may ask, what does this mean exactly? Well, lets say you are trying to figure out how to automate your pokemon go account to hatch more eggs or whatever you hatch in pokemon go. You would first need to proxy traffic from your phone through a debugger such as Charles Web Debugger, and then you could theoretically see the calls being made to the go servers rest api. The only problem is that app developers are getting craftier in the ways they protect their interests. Nowadays its very likely that once you reverse engineer an applications network connection, instead of seeing the typical json responses such as {‘walk”:”true”,”direction:left”}. You may see something more like {‘GTFO”:”234234234234DSFSDFSDF”} and a link to a job application. This is frustrating for me especially because I don’t like jobs and I don’t like wearing pants. So what is a developer to do?

Automated Android Virtual Device based third party hacker api.

In the past, using android virtual devices was a nightmare. They were so painfully slow I would have nightmares about 6 foot slugs trying to chase me. Today however the Android Virtual Devices run on x86 and 64 bit emulators and you can easily run 4 at a time on a $50 computer purchased off craigslist.

This rig was designed to run Windows 7 and features a quad core Xeon processor, a nameless ati 300x graphics card, 6 gigabytes of ram, and a terabyte drive pulled from an old power-edge 2950 hanging out in my garage. (I also had to buy a DVI to HDMI connector for $14.99 at WalMart)

20170917_143207

So I went and installed the Android SDK with the Haxm emulator enabled and I allowed 4gb of ram so each emulator can use up to a gig. I then added the necessary programs to my windows PATH variable.

C:\Users\nerd\AppData\Local\Android\sdk\platform-tools

C:\Users\nerd\AppData\Local\Android\sdk\emulator

Next, we install a tool we will definitely need in order to read whats on the screen of your app. Its called tesseract, and its a free optical character recognition software that works very well. If you are using ubuntu you can just install it via repo. For windows, I installed the 4.0 alpha made with MinGW which you can get download here.

Once that is installed, add tesseract to your windows path so it can be used by our application

C:\Program Files (x86)\Tesseract-OCR

Another thing we will need is a tool called imagick. This is an image manipulation program that we will be using  to process images from your android virtual machine in order to read text using Tesseract-OCR. You can download imageick here.  Make sure to click on the option “convert”, tool option when installed. Add imageick to your PATH variable as well.

C:\Program Files\ImageMagick-7.0.7-Q16

 

Ok that was a lot of work. Now that we have our pre-requisites installed, we can go ahead and set up an Android Virtual machine. I would recommend using one with a 4 inch screen or less with an older API. Make sure to select an x86 image labeled “Google API”, so that you can use the google maps feature.

 

Capture

A very important make or break thing to do is to set your graphics processor to Software if you are using an older system. Otherwise you might end up with a slug slow AVD.

4k2CASDSRy-12

 

The Coding Part

At this point you should have Tesseract, Imageick, and the Android SDK installed with a properly configured android virtual machine. Aside from some functioning code, we have everything we need to get cracking on an API.  Before we begin there is one more thing we need discuss. You may have asked yourself, “How are you going to publicize an API using a $50 craigslist computer at home”. This answer is that I is and I isn’t. I’m using the free logmein hamachi vpn software which allows anyone with basic computer skills to connect up to 5 computers on a lan like network no matter where they are in the world. It works so well that I use it for everything. They have a free version for linux that even works on raspberry pi’s and chipp computers. So essential what I do is I take user input from a public website written in Laravel, and then when I need to process a job I use the built in Job Queue and send the data over using php’s file_get_contents() like so.

file_get_contents(‘http://hamachi_ip:3000/api/trigger_emulator?variable1&variable2’)

 

Now we are going to wrap this post up by including some code snippets required to automate your android virtual machine.  Below is a basic nodejs program for starting an app, setting the gps location, swiping left, and recording the data to a database. These snips are pulled from a much larger program and you will likely need to update paths and do some work.  The android auth_token is specific to your machine and is inside your C:\Users\username folder as emulator_auth_token. This below code will listen on port 3000. Add logic to the /do_stuff endpoint to do something useful.

/* imports *//* imports */
var fs = require(‘fs’);
const mysql = require(‘mysql’);
var sleep = require(‘system-sleep’);
var Telnet = require(‘telnet-client’)
const { exec } = require(‘child_process’);
const bodyParser = require(‘body-parser’);
const tesseract = require(‘node-tesseract’);
var elasticsearch = require(‘elasticsearch’);
var gm = require(‘gm’).subClass({imageMagick: true})
var ssh2 = require(‘ssh2’);
const express = require(‘express’),   app = express(),
port = process.env.PORT || 3000;

/* variable declaration */
var ssh_conn = new ssh2();
var swipe_limit = 250;
var connection = new Telnet()
var bridge_devices = new Array();
var emulator_console_auth_token = “YOURS”;
var limit_reached = false;
var available_devices = [];
var android_device_id = “none”;
var in_use_bridge_devices = [];
var router = express.Router();
var avd_designations = [‘avd_b’];
var adb_path = ‘C:\\Users\\nerd\\AppData\\Local\\Android\\sdk\\platform-tools\\adb’;
var image_destination_path = “C:\\Users\\nerd\\Desktop\\avd_b_screenshots\\”;
/* var init */
var con = mysql.createConnection({
host: “YOURS”,
user: “YOURS”,
password: “YOURS”,
database : ‘YOURS’
});
// var elastic_client = new elasticsearch.Client({//   host: ‘25.63.127.57:9200’,//   log: ‘trace’// });
con.connect(function(err) {
if (err) {console.log(“error”+err);}

console.log(“Connected!”);

})
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(‘/api’, router);
/* api routes */
router.get(‘/do_stuff’, function(req, res) {
var geo = req.query.geo;
var device = req.query.device;
searchUsers(geo, device);
});
/* function declaration */

 

function clearImages(avd){
exec(adb_path+’ -s ‘+avd+” shell rm -rf /sdcard/*.png”, function(err, data) {                 console.log(err)
console.log(data.toString());                           });

}
function getDevices(){
exec(adb_path+’ devices’, function(err, data) {                  var raw_bridge_devices = data.split(“\n”);
for (var i = 1; i < raw_bridge_devices.length; i++){                if(raw_bridge_devices[i].length >= 1){                if(raw_bridge_devices[i].includes(‘device’)){
var device = raw_bridge_devices[i].split(/\s+/);
bridge_devices.push(device[0]);

}
}
}                       });    }
function goBack(avd){
exec(adb_path+’ -s ‘+avd+” shell input keyevent 4″, function(err, data) {                 console.log(err)
console.log(data.toString());                           });
}
function startAVD(avd){
exec(‘C:\\Users\\nerd\\AppData\\Local\\Android\\sdk\\emulator\\emulator -avd ‘+avd, function(err, data) {                  console.log(err)
console.log(data.toString());
});   }
function startAPP(avd,app){
exec(adb_path+’ -s ‘+avd+’ shell monkey -p ‘+app+’ -c android.intent.category.LAUNCHER 1′, function(err, data) {                         });
}
function stopAPP(avd,app){
exec(adb_path+’ -s ‘+avd+’ shell am force-stop ‘+app+’ -c android.intent.category.LAUNCHER 1′, function(err, data) {                         });
return;
}
function readImage(device,image_path,geo,image_file_name){
console.log(‘readin dat image’);
/* gets text from image */
tesseract.process(image_path,function(err, text) {
if(err) {
console.error(err);
} else {
console.log(‘readed dat image’);
console.log(text);
// elastic_insert(text);
}
});
}

 

function saveUserData(text,geo,image_path,image_file_name){
/* this parts up to you */
}

function setAVDGeo(geo_c,device){ var geo_switch =  geo_c.split(“,”); var geo = geo_switch[1]+” “+geo_switch[0]; console.log(“geo fix “+geo); telnet_port_array = device.split(“-“);
telnet_port = telnet_port_array[1];
var params = {  host: ‘127.0.0.1’,  port: telnet_port,  shellPrompt: ‘OK’,  timeout: 50000,  // removeEcho: 4 }
connection.on(‘ready’, function(prompt) {  connection.exec(“auth “+emulator_console_auth_token, function(err, response) {    console.log(response)     sleep(2000);            connection.exec(“geo fix “+geo, function(err, response) {       console.log(response);
})
sleep(2000);
}) })
connection.on(‘timeout’, function() {  console.log(‘socket timeout!’)  connection.end() })
connection.on(‘close’, function() {  console.log(‘connection closed’) })
connection.connect(params);
}

 

function swipeLeft(avd){
/* swip app left */
exec(adb_path+’ -s ‘+avd+” shell input swipe 1000 500 -2000 500 2500″, function(err, data) {                 // console.log(err)
console.log(data.toString());                           });
}
function takeScreenshot(avd,image_name){
/* log into android virtual machine, take screen shot, move to desktop */
exec(adb_path+’ -s ‘+avd+” shell screencap /mnt/sdcard/”+image_name, function(err, data) {                 // console.log(err)
console.log(data.toString());
exec(adb_path+’ -s ‘+avd+” pull /mnt/sdcard/”+image_name+ ” “+image_destination_path+image_name , function(err, data) {               console.log(data.toString());                                   });
});
}
function preProcessImage(image_path){
/* convert text to black for tesseract ocr */
exec(‘convert “‘+image_path+'” -fuzz 5% -fill black -opaque “#a6a6a6” ‘+image_path+’.tmp.png’, function(err, data) {                 // console.log(err)
console.log(data.toString());

});  }

startAVD(‘avd_b’);
app.listen(port);

 

 

Finally

Take a nap and give up. Someone else will probably take care of you.

20170917_165427

 

 

 

Advertisements