[工具]反编译APK和XML

        接SDK坑的就是配置文件这些,为了防止出问题,也是为了学习,最近一直在反编译一些游戏的APK,获取AndroidManifest.xml。用到了2个jar包,一个是AXMLPrinter2.jar,另一个则是主程给我的apktool_2.3.4.jar。2个都在用,AXMLPrinter2.jar反编译后的布局很舒服,不是堆在一起,看起来不是很累,但有个问题是很多显示都是数字(比如android:screenOrientation)。

        这个咋看,太累了。另一个apktool_2.3.4.jar则是全部反编译,就是反编译时候稍微比较耗时,但是内容显示较全。不嫌累的话,可以用命令行来实现,但每次拷贝命令行代码太烦,就写了个工具来实现。先列下这2个jar包的命令行:

AXMLPrinter2.jar:

        java -jar E:\\ZP\\DecompileXml\\AXMLPrinter2.jar xxx.xml > xxx.xxx

        E:\\ZP\\DecompileXml\\AXMLPrinter2.jar是jar包存放目录,xxx.xml是需要反编译的XML文件,xxx.xxx则是需要反编译后生成的文件,txt和xml都可以。(其他没测)

apktool_2.3.4.jar:

        java -jar E:\\ZP\\DecompileXml\\apktool_2.3.4.jar d -f xxx.apk -o xxx

        E:\\ZP\\DecompileXml\\apktool_2.3.4.jar是jar包存放目录,xxx.apk是需要反编译的XML文件,xxx则是需要反编译后存放的目录。

        先来看下界面样式,多么符合程序美:

        代码:

#define WIN32_LEAN_AND_MEAN

#define APP_NAME TEXT("DecompileXml")
#define APP_WIDTH 600
#define APP_HEIGHT 480

#include <Windows.h>
#include "resource.h"
#include <commdlg.h>
#include <ShlObj.h>
#include <iostream>
#include <fstream>

#pragma region Global Variables
HINSTANCE g_Hinstance;
HWND g_hDialog;
bool b_DecompileXml = false;
#pragma endregion

#pragma region Declaration: Create UI
bool CreateUI(HWND hwnd);
#pragma endregion

#pragma region Declaration: UI Event
void OnBtnXMLClick();
void OnBtnOutputClick();
void OnBtnCommandClick();
#pragma endregion

#pragma region Declaration: Command
void GetXMLFile();
void GetAPKFile();
void GetOutputDirectory();
void DecompileXML();
void DecompileAPK();
#pragma endregion

#pragma region Declaration: Message Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
#pragma endregion

#pragma region Main Entry
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
	g_Hinstance = hInstance;

	WNDCLASSEX wc;
	wc.cbClsExtra = 0;
	wc.cbSize = sizeof(wc);
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hIconSm = wc.hIcon;
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = APP_NAME;
	wc.lpszMenuName = nullptr;
	wc.style = CS_HREDRAW | CS_VREDRAW;

	if (!RegisterClassEx(&wc))
	{
		MessageBox(NULL, TEXT("RegisterClassEx function - failed"), TEXT("Error"), MB_OK | MB_ICONERROR);
		return 0;
	}

	int screenWidth = GetSystemMetrics(SM_CXSCREEN);
	int screenHeight = GetSystemMetrics(SM_CYSCREEN);
	int posX = (screenWidth - APP_WIDTH) / 2;
	int posY = (screenHeight - APP_HEIGHT) / 2;

	HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW,
		wc.lpszClassName,
		wc.lpszClassName,
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
		posX, posY,
		APP_WIDTH, APP_HEIGHT,
		NULL,
		NULL,
		hInstance,
		nullptr);
	if (!hwnd)
	{
		MessageBox(NULL, TEXT("CreateWindowEx function - failed"), TEXT("Error"), MB_OK | MB_ICONERROR);
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	MSG msg;
	memset(&msg, 0, sizeof(msg));

	while (msg.message != WM_QUIT)
	{
		if (GetMessage(&msg, NULL, 0, 0))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}
#pragma endregion

#pragma region Implementation: Create UI
bool CreateUI(HWND hwnd)
{
	g_hDialog = CreateDialog(g_Hinstance, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, (DLGPROC)DlgProc);
	if (!g_hDialog)
	{
		MessageBox(NULL, TEXT("CreateDialog function - failed"), TEXT("Error"), MB_OK | MB_ICONERROR);
		return false;
	}
	ShowWindow(g_hDialog, SW_SHOW);

	// 设置为桌面路径
	char outputDirectory[MAX_PATH] = { 0 };
	SHGetSpecialFolderPath(0, outputDirectory, CSIDL_DESKTOPDIRECTORY, 0);
	HWND hTempEditOutput = GetDlgItem(g_hDialog, IDC_EDIT_Output);
	SetWindowText(hTempEditOutput, outputDirectory);

	return true;
}
#pragma endregion

#pragma region Implementation: UI Event
void OnBtnXMLClick()
{
	if(b_DecompileXml)
		GetXMLFile();
	else
		GetAPKFile();
}

void OnBtnOutputClick()
{
	GetOutputDirectory();
}

void OnBtnCommandClick()
{
	if (b_DecompileXml)
		DecompileXML();
	else
		DecompileAPK();
}
#pragma endregion

#pragma region Declaration: Command
void GetXMLFile()
{
	char xmlPath[MAX_PATH] = { 0 };

	OPENFILENAME ofn;
	memset(&ofn, 0, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.lpstrFilter = TEXT("xml Files (*.xml)\0*.xml\0All Files (*.*)\0*.*\0");
	ofn.lpstrFile = xmlPath;
	ofn.nMaxFile = MAX_PATH;
	ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	ofn.lpstrDefExt = TEXT("xml");         //默认的打开的文件类型
	ofn.lpstrInitialDir = TEXT(".\\");     //默认的打开的文件路径,这里以当前目录为例

	if (GetOpenFileName(&ofn))
	{
		if (g_hDialog != NULL)
		{
			HWND hTempEditXml = GetDlgItem(g_hDialog, IDC_EDIT_XML);
			SetWindowText(hTempEditXml, xmlPath);
		}
	}
}

void GetAPKFile()
{
	char apkPath[MAX_PATH] = { 0 };

	OPENFILENAME ofn;
	memset(&ofn, 0, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.lpstrFilter = TEXT("apk Files (*.apk)\0*.apk\0All Files (*.*)\0*.*\0");
	ofn.lpstrFile = apkPath;
	ofn.nMaxFile = MAX_PATH;
	ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	ofn.lpstrDefExt = TEXT("apk");         //默认的打开的文件类型
	ofn.lpstrInitialDir = TEXT(".\\");     //默认的打开的文件路径,这里以当前目录为例

	if (GetOpenFileName(&ofn))
	{
		if (g_hDialog != NULL)
		{
			HWND hTempEditXml = GetDlgItem(g_hDialog, IDC_EDIT_XML);
			SetWindowText(hTempEditXml, apkPath);
		}
	}
}

void GetOutputDirectory()
{
	BROWSEINFO bi;
	memset(&bi, 0, sizeof(bi));
	bi.ulFlags = BIF_BROWSEFORCOMPUTER | BIF_EDITBOX | BIF_NEWDIALOGSTYLE;
	bi.lpszTitle = "请选择反编译后文件存放目录";

	LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
	if (!pidl) return;

	char outputDirectory[MAX_PATH] = { 0 };
	SHGetPathFromIDList(pidl, outputDirectory);
	if ('\0' == outputDirectory[0])
		MessageBox(NULL, "获取文件存放目录有误", "错误", MB_OK | MB_ICONERROR);
	else
	{
		if (g_hDialog != NULL)
		{
			HWND hTempEditOutput = GetDlgItem(g_hDialog, IDC_EDIT_Output);
			SetWindowText(hTempEditOutput, outputDirectory);
		}
	}
}

void DecompileXML()
{
	if (NULL == g_hDialog) return;

	char xmlPath[MAX_PATH] = { 0 };
	HWND hTempEditXml = GetDlgItem(g_hDialog, IDC_EDIT_XML);
	GetWindowText(hTempEditXml, xmlPath, MAX_PATH);

	char outputDirectory[MAX_PATH] = { 0 };
	HWND hTempEditOutput = GetDlgItem(g_hDialog, IDC_EDIT_Output);
	GetWindowText(hTempEditOutput, outputDirectory, MAX_PATH);
	
	char outputXmlPath[MAX_PATH] = { 0 };
	char* findStr = strrchr(xmlPath, '\\');
	++findStr;// 去掉'\\'
	strcpy_s(outputXmlPath, strlen(outputDirectory) + 1, outputDirectory);
	char preName[] = "\\Decompile_";
	strcat_s(outputXmlPath, strlen(outputXmlPath) + strlen(preName) + 1, preName);
	strcat_s(outputXmlPath, strlen(outputXmlPath) + strlen(findStr) + 1, findStr);

	char commandStr[MAX_PATH] = { 0 };
	char command[] = "java -jar E:\\ZP\\DecompileXml\\AXMLPrinter2.jar ";
	strcpy_s(commandStr, strlen(command) + 1, command);
	strcat_s(commandStr, strlen(commandStr) + strlen(xmlPath) + 1, xmlPath);
	char convertStr[] = " > ";
	strcat_s(commandStr, strlen(commandStr) + strlen(convertStr) + 1, convertStr);
	strcat_s(commandStr, strlen(commandStr) + strlen(outputXmlPath) + 1, outputXmlPath);

	FILE* file = _popen(commandStr, "r");
	if (file != nullptr)
		_pclose(file);
}

void DecompileAPK()
{
	if (NULL == g_hDialog) return;

	char apkPath[MAX_PATH] = { 0 };
	HWND hTempEditXml = GetDlgItem(g_hDialog, IDC_EDIT_XML);
	GetWindowText(hTempEditXml, apkPath, MAX_PATH);

	char outputDirectory[MAX_PATH] = { 0 };
	HWND hTempEditOutput = GetDlgItem(g_hDialog, IDC_EDIT_Output);
	GetWindowText(hTempEditOutput, outputDirectory, MAX_PATH);

	char outputApkPath[MAX_PATH] = { 0 };
	char* findStr = strrchr(apkPath, '\\');
	++findStr;// 去掉'\\'
	char outputFileName[MAX_PATH] = { 0 };
	strncpy_s(outputFileName, MAX_PATH, findStr, strlen(findStr) - strlen(".apk"));//获取APK name

	strcpy_s(outputApkPath, strlen(outputDirectory) + 1, outputDirectory);
	char preName[] = "\\Decompile_";
	strcat_s(outputApkPath, strlen(outputApkPath) + strlen(preName) + 1, preName);
	strcat_s(outputApkPath, strlen(outputApkPath) + strlen(outputFileName) + 1, outputFileName);

	char commandStr[MAX_PATH] = { 0 };
	char command[] = "java -jar E:\\ZP\\DecompileXml\\apktool_2.3.4.jar d -f ";
	strcpy_s(commandStr, strlen(command) + 1, command);
	strcat_s(commandStr, strlen(commandStr) + strlen(apkPath) + 1, apkPath);
	char convertStr[] = " -o ";
	strcat_s(commandStr, strlen(commandStr) + strlen(convertStr) + 1, convertStr);
	strcat_s(commandStr, strlen(commandStr) + strlen(outputApkPath) + 1, outputApkPath);

	FILE* file = _popen(commandStr, "r");
	if (file != nullptr)
		_pclose(file);
}
#pragma endregion

#pragma region Implementation: Message Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_CREATE:
	   {
			bool result = CreateUI(hwnd);
			if (!result)
				PostQuitMessage(0);
	   }
	   break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_KEYDOWN:
		{
			switch ((char)wParam)
			{
			case VK_ESCAPE:
				PostQuitMessage(0);
				break;
			}
		}
		break;
	}

	return DefWindowProc(hwnd, msg, wParam, lParam);
}

INT_PTR CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
		case WM_COMMAND:
		{
			switch (wParam)
			{
			case IDC_BUTTON_XML:
				OnBtnXMLClick();
				break;
			case IDC_BUTTON_Output:
				OnBtnOutputClick();
				break;
			case IDC_BUTTON_Command:
				OnBtnCommandClick();
				break;
			}
		}
		break;
	}

	return 0;
}
#pragma endregion

        代码其实很简单,就不做解释了,有兴趣的可以研究下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值