Porting your favourite cmdline tool to Android

Post on 19-Feb-2017

689 views 0 download

transcript

PORTING TO ANDROID

PORTING YOUR FAVOURITE CMDLINE TOOL

TO ANDROID

Vlatko Kosturjak (@k0st), Droidcon Zagreb, 30th of April

AGENDAIntroductionNative codeToolchainsThings I wish I knew in advanceCalling native executablesIssues and implicationsSummaryQuestions and answers

45 minutes

ABOUT ME

Security Consultant in DivertoLinux and FLOSS enthusiastOpen source developer

Have code in OpenVAS, Nmap, Metasploit, ...

Android "developer" since 2010started counting from first Market appmostly focused on NDK and ADK

https://github.com/kost

ABOUT ME IN PICTURES

ABOUT ME IN PICTURES

INTRODUCE ELEPHANTTalk will cover

producing standalone binaries

executing standalone binaries

Talk is mostly about Nmap experience

Most Nmap frontends on playstore are using this port

in source or binary form

Talk will NOT cover

producing libraries or JNI

integrating with Android Studio

https://github.com/kost/nmap-android

https://github.com/kost/NetworkMapper

NATIVE CODE

NOT your Java code :)

It's mostly about

C/C++

Assembler

Not portable across platforms

For each platform, you need different binary

x86

arm

mips

WHY BOTHER WITH NATIVE CODE?performancelegacy codecode reuseyou just need that tool

WHAT'S THE PROCESS?compiling

compiling on same machinecross-compiling

compiling on (host) machine for other (target) machine

TOOLCHAINSAndroid NDK

Commercial

Open Source

Custom

CUSTOM TOOLCHAINYour own version of compilerYour own version of build scriptsCustom

COMMERCIAL

EmbarcaderoGood old Borland...

XamarinNative apps in C#

...

OPEN SOURCE / FREE

Crystax

drop-in replacement for Google's NDK

WCHAR, locales, full C+11 standard library...

Buildroot

Standard embedded cross compilation toolchain

ARM, x86, MIPS

Scratchbox

ARM, x86, MIPS (experimental)

Anyone remembers Maemo? :)

...

ANDROID NDK

Android official toolchain

Available for free from developer.android.com

Bionic

No full ANSI C support

locale

different threads

Patch as you grow

standalone binary support/bugs

stdout symbol bug

WCHAR support

standard library support

WHAT'S THE FUZZ?

Download NDKDownload tool you want to port

./configure --host=arm-linux-androideabimakemake install

It works - go home!

IN CASE IT IS HELLO WORLD.../* Hello World program */

#include <stdio.h>

void main()

{

printf("Hello World");

}

It works pretty well indeed.

IN REAL WORLD

Code isn't perfectNot portableEndianessPath SeparatorsDependenciesExtensions3rd party libraries

TWO WAYS TO INVOKE COMPILER

Calling with sysrootexport CC="$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc"

export CFLAGS="--sysroot=$SYSROOT"

$CC $CFLAGS -o hello hello.c

Producing directory for target

$NDK/build/tools/make-standalone-toolchain.sh --platform=android-3 --install-dir=/

/opt/ndk3/bin/arm-linux-androideabi-gcc -o hello hello.c

NDK PLATFORMS

NDK platform Platforms 32/64 bit

3 ARM 32

9 ARM/MIPS/Intel 32

21 ARM/MIPS/Intel 64

PROCESS OF CROSS COMPILING

Compile and fix as you go :)sorry, no single recipe

Standard problemsstdout bugold autoconf/automake support filesarm-linux-androideabi missing

In shortnothing that google/stackoverflow can't help :)

STATIC VS DYNAMIC LINKINGDynamic

small sizerun-time dependency

Staticlarge sizeno dependencies

LIFE IS PERFECTStatic binaries working like a charm

“until resolv.conf disappeared :) ”

DNS PROBLEMS

int main(int argc,char *argv[]) {

int i;

struct hostent *hp;

for ( i=1; i<argc; ++i ) {

hp = gethostbyname(argv[i]);

if ( !hp ) {

fprintf(stderr, "%s: host '%s'\n", hstrerror(h_errno),

argv[i]);

continue;

}

printf("Host:\t%s\n" ,argv[i]);

printf("\tResolves to:\t%s\n", hp->h_name);

}

}

Original at gist

DNS AND RESOLV.CONF

#ifdef ANDROID_CHANGES /* READ FROM SYSTEM PROPERTIES */ dns_last_change_counter = _get_dns_change_count(); [..]#else /* !ANDROID_CHANGES - IGNORE resolv.conf in Android */#define MATCH(line, name) \ [..]

Original at https://code.google.com/p/android-source-

browsing

DYNAMIC VS STATIC

Type Size Dependency DNS OOTB

Dynamic smaller yes yes

Static bigger no no

Mixed medium yes (basic) yes

HERE COMES LOLIPOPerror: only position independent executables (PIE) are supported.

Position Independent Executable (PIE)PIE support appeared in API level 16Finally they implemented it :)

Too bad binaries does not work

WHAT'S PIE?

Position Independent Executable (PIE)

Security protection

better Address Space Layout Randomization (ASLR)

Exploitation mitigation technique

Harder return-to-libc exploitation

Requirements

PIE required for dynamic executables

PIE not required for static executables

PIE EXAMPLE#include <stdio.h>

int global;

int checkadr (int *bla){ int local; printf("bla adr = %p\n", &bla); printf("global adr = %p\n", &global); printf("local adr = %p\n", &global);}

int main (void) { int c; printf("c adr = %p\n", &c); printf("checkadr adr = %p\n", &checkadr);

PIE SUPPORT

Android version Supported Required

1,2,3 no no

4 yes no

5 yes yes

PIE WORKAROUND

Way to run PIE executables on non supported systemsif system suppports PIE

just run executableif system does not suppport PIE

use run_pie.crun_pie your_proggy args

CFLAGS +=-fvisibility=default -fPIELDFLAGS += -rdynamic -pie

https://gist.github.com/kost/5fd4628f45a4995bec28

CALLING NATIVE EXECUTABLESp = Runtime.getRuntime().exec(command);p.waitFor();BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));String line;while ((line = reader.readLine()) != null) { output.append(line).append("\n");}

BETTER WAY - USING

PROCESSBUILDER

ProcessBuilder processBuilder = new ProcessBuilder(shellToRun);

processBuilder.redirectErrorStream(true);

scanProcess = processBuilder.start();

outputStream = new DataOutputStream(scanProcess.getOutputStream());

inputStream = new BufferedReader(new InputStreamReader(scanProcess.getInputStream()));

while (((pstdout = inputStream.readLine()) != null)) {

output.append(pstdout).append("\n");

}

RUNNING BINARIES AS ROOT

Not needed to set any new android permission

Historic references to SUPERUSER permissions

Not much different than executing as normal user

Have to Runtime.getRuntime().exec("su")

Write commands to stdin of process

Loop the output

ROOT IMPLICATIONS

Killing run away root processes

Hard as it can be due to blocking nature

UI does not have root access

Killing spawned root processes

parse ps output

spawn su shell

kill process

SECURITY IMPLICATIONS

Native binary problemsMemory corruption attacks (Buffer overflows, ...)Format string problems......

PermissionsCommand injections

SECURITY IMPLICATIONS -

PERMISSIONS

Setting insecure permissions to executables/libraries

Very common when something does not work

Dangerous and heroic

Other apps can write to your bin or library

Exploitation

Find insecure .so library, inject your code

Find insecure binary, replace it with your version!

echo "#!/bin/sh" > /data/data/com.heroic.app/bin/mybinaryecho "echo '0wned!'" >> /data/data/com.heroic.app/bin/mybinary

SECURITY IMPLICATIONS -

UNTRUSTED INPUT

Passing untrusted/unvalidated input to shellRunning native executables can lead to commandinjections

Extremely dangerous if running as userExtremely heroic and dangerous if running as root

Pay special attention to exported activitiesother apps can call that intentwhich means they can execute commands as yourapp!!

UNTRUSTED INPUT EXAMPLEBundle b = getIntent().getExtras();

configFilePath = b.getString("path");

[..]

ShellExecuter exe = new ShellExecuter();

return exe.Executer("cat " + configFilePath);

<activity

android:name=".MyHeroicActivity"

....

android:exported="true" />

UNTRUSTED INPUT EXPLOITATION

public void onBtnClick(View view) { Intent intent = new Intent(); intent.setClassName("com.heroic.app", "com.heroic.app.MyHeroicActivity" intent.putExtra("path", "/system/etc/hosts; echo 'Owned' > /data/data/com.heroic.app/bin/binary" startActivity(intent);}

ON THE END..You get bad comments :)

Don't use ratings for bug reports ;)

Please submit VERBOSE bug reports to author directly

FORTUNATELY

Fortunately, there are good comments ;)

Thanks on these

SUMMARYPorting is quite possible

Not as easy as marketing says

You can't configure; make; make install in most cases

Expect you'll have to patch if project is bigger

Not that hard

If you know requirements upfront

Have listened to this lecture carefully

Be aware of security implications!

THANKS ON LISTENING

?ANY QUESTIONS?