逆向工程(又称逆向技术),是一种产品设计技术再现过程,即对一项目标产品进行逆向分析及研究,从而演绎并得出该产品的处理流程、组织结构、功能特性及技术规格等设计要素,以制作出功能相近,但又不完全一样的产品。逆向工程源于商业及军事领域中的硬件分析。其主要目的是在不能轻易获得必要的生产信息的情况下,直接从成品分析,推导出产品的设计原理。
逆向工程可能会被误认为是对知识产权的严重侵害,但是在实际应用上,反而可能会保护知识产权所有者。例如在集成电路领域,如果怀疑某公司侵犯知识产权,可以用逆向工程技术来寻找证据。
这里我们以安卓项目开始探索逆向工程之路
工欲善其身,必先利其器。
APKTool: 本文重要工具,APK逆向工具,使用简单下载地址: http://ibotpeaches.github.io/Apktool/install/
这里简单介绍下大概流程,首先把后缀为.apk的文件改为.zip的一个压缩文件,方便解压。dex2jar和jd-gui配套使用,用于逆向代码部分,APKTool用于逆向res文件夹下的图片布局等部分。
新建一个项目,名字是 Androidrefirst,实现的逻辑是在输入框内填写 2019之后 点击按钮跳转到成功页面。
主要代码如下
package com.example.androidrefirst; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private EditText code; private Button btn_verify; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { code = findViewById(R.id.editText); btn_verify = findViewById(R.id.button); btn_verify.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String verifyCode=code.getText().toString().trim(); if(verifyCode.equals("2019")){ Intent intent=new Intent(MainActivity.this,SuccessActivity.class); startActivity(intent); }else { Toast.makeText(MainActivity.this,"验证码错误!", Toast.LENGTH_LONG).show(); } } }); } }
生成 apk安装包 app-release.apk
需要用到的是dex2jar包里面的三个文件(当前是在windows环境下,Mac环境用对应的.sh文件):
d2j_invoke.bat
d2j-dex2jar.bat
lib
将这三个文件复制到一个空的文件夹内,将刚才.apk解压后的classes.dex文件也一起复制到这里
可以看到我们的代码
package com.example.androidrefirst; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private Button btn_verify; private EditText code; private void init() { this.code = (EditText)findViewById(2131230782); this.btn_verify = (Button)findViewById(2131230755); this.btn_verify.setOnClickListener(new View.OnClickListener() { public void onClick(View param1View) { if (MainActivity.this.code.getText().toString().trim().equals("2019")) { Intent intent = new Intent((Context)MainActivity.this, SuccessActivity.class); MainActivity.this.startActivity(intent); } else { Toast.makeText((Context)MainActivity.this, ", 1).show(); } } }); } protected void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2131427356); init(); } }
对照着自己的手写的代码,已经差不离十了,对于想要代码思路的我们来说,到这里已经基本可以摸透他的逻辑。
apktool下载后会有两个文件,一个.jar(例如apktool_2.3.3.jar 需要把名字改成apktool.jar) 一个apktool.bat 。
同刚才一样在cmd命令下进入刚才文件夹(同样可以新建一个),连同我们刚才那个后缀为apk的安装包一起放入,输入如下命令
apktool d app-release.apk # 此处app-release为apk名称
得到一个新的app-release(对应apk名称)文件夹
这个app-release文件夹下会得到若干文件,主要内容介绍如下:
修改原代码逻辑
我们只需要修改if后面的判断条件,设置为否即可if (!MainActivity.this.code.…),这样就成功绕过了条件约束。
接下来还有一部很重要那就是修改smali文件,找到MainActivity$1.smali这个文件用代码查看工具打开
找到这个if-eqz 修改成if-nez (nez对应为非,符号“!”),到这里要修改的部分都成功了,最后一步要做的就是重新打包了。当然对smali语法感兴趣的可以一起探讨学习。
在apktool文件夹路径的cmd下输入:
apktool b [文件夹] -o test2.apk #(test2为新apk名称,[文件夹]为对应的有修改需要打包的文件夹) #例如:我当前就可以这样写 apktool b [E:/tools/apktool/app-release] -o test2.apk
至此,我们的目标apk文件已经生成,当然如果你想装到你自己手机上还需要重新签名一下。
首先我们需要一个用于签名的.keystore文件,生成命令如下(这里我们假设生成的是demo.keystore)。
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore # (cmd到apktool文件夹下跟待签名的apk放同个文件夹内便于操作)
这里我们利用Java JDK提供的一个jarsigner进行签名,在刚才的cmd下继续操作,输入:
jarsigner -verbose -keystore demo.keystore test2.apk demo.keystore
以上。我们目的apk已经可以投入使用,如果需要更快更好的体验还需要进行一次字节对齐的操作(后续分析)。
参考:
https://blog.csdn.net/micaaa/article/details/82426710