[工具]反编译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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 反编译 APK 是指将已打包的 APK 文件解包,提取出其中的源代码、资源文件等信息进行分析和修改的过程。在实际开发和研究中,反编译 APK 可以帮助开发者了解其他应用程序的实现逻辑、修改应用程序的功能或者进行安全评估。 反编译 APK 可以通过教程和工具来完成。首先,需要下载并安装一个专门用于反编译 APK工具,比如 Apktool、dex2jar 等。接下来,可以通过搜索引擎或者查找相关教程来学习如何使用这些工具进行反编译。 具体来说,使用 Apktool 可以将 APK 解包成对应的 smali 代码文件和资源文件,而使用 dex2jar 可以将 APK 中的 dex 文件转换为 jar 文件。 在进行反编译 APK 之前,我们需要了解一些基本的 Android 开发知识,比如 Java 编程语言、Android 开发框架、AndroidManifest.xml 配置文件等。只有对这些知识有一定的了解,才能更好地理解和修改反编译后的代码。 需要注意的是,反编译 APK 是一种合法的行为,但在修改他人应用程序时需要遵守法律法规,避免侵权和非法行为。同时,也要强调,反编译 APK 只是为了学习和研究目的,对于商业应用的源代码和资源文件进行非法的使用和传播是不道德和不合法的。 总之,Android 反编译 APK 是一个有用的技术,在开发和研究中有着重要的作用。通过教程和工具,我们可以将 APK 解包,获取源代码和资源文件,进行分析和修改,但使用反编译的成果需要遵守法律法规,并避免侵权和非法行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值