1. apk安装到手机,一样的界面,随便输入一样的报错

2. apk拖入到jadx重看看

public native String sha1(String str);

    static {
System.loadLibrary("native-lib");
} /* JADX INFO: Access modifiers changed from: protected */
@Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
initViews();
} private void initViews() {
this.edt_code = (EditText) findViewById(R.id.edt_code);
this.edt_username = (EditText) findViewById(R.id.edt_username);
Button button = (Button) findViewById(R.id.btn_register);
this.btn_register = button;
button.setOnClickListener(new View.OnClickListener() { // from class: com.r0ysue.sha1.MainActivity.1
@Override // android.view.View.OnClickListener
public void onClick(View view) {
String obj = MainActivity.this.edt_username.getText().toString();
if (MainActivity.this.sha1(obj).equals(MainActivity.this.edt_code.getText().toString())) {
Toast.makeText(MainActivity.this, "SUCCESS!", 0).show();
} else {
Toast.makeText(MainActivity.this, "ERROR!", 0).show();
}
}
});
}

和第一题的套路一样,native方法名换成了sha1

3. 导出so,放入IDA中进行分析

jstring __fastcall Java_com_r0ysue_sha1_MainActivity_sha1(JNIEnv *env, jobject object, void *str)
{
char *v4; // x20
__int64 v5; // x23
char *v6; // x20
char v8[44]; // [xsp+4h] [xbp-7Ch] BYREF
char v9[24]; // [xsp+30h] [xbp-50h] BYREF
__int64 v10; // [xsp+48h] [xbp-38h] v10 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
v4 = (char *)(*env)->GetStringUTFChars(env, str, 0LL);
strlen(v4);
sub_1BC0((int)v9, v4);
v5 = 0LL;
v6 = v8;
do
{
sub_7E8(v6, -1LL);
++v5;
v6 += 2;
}
while ( v5 != 20 );
return (*env)->NewStringUTF(env, v8);
}

进入sub_1BC0中看看

__int64 __fastcall sub_1BC0(int a1, void *a2)
{
__int128 v4; // [xsp+0h] [xbp-80h] BYREF
__int64 v5; // [xsp+10h] [xbp-70h]
int v6; // [xsp+18h] [xbp-68h]
__int64 v7; // [xsp+68h] [xbp-18h] v7 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
v4 = xmmword_1C50;
v5 = 0xC3D2E1F0LL;
v6 = 0;
sub_19F0((int)&v4, a2);
return sub_1AD4(a1, (int)&v4);
}

这个0xC3D2E1F0很眼熟,查了一些果然是sha1的特征初始化常量之一

sha1 初始化常量
A = 0x67452301
B = 0xEFCDAB89
C = 0x98BADCFE
D = 0x10325476
E = 0xC3D2E1F0 sha1 常量K
K = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6]
0≤t≤19 K = 0x5A827999
20≤t≤39 K = 0x6ED9EBA1
40≤t≤59 K = 0x8F1BBCDC
60≤t≤79 K = 0xCA62C1D6

既然已经找到了第一个,看看xmmword_1C50 会不会有所发现

0000000000001C50  01 23 45 67 89 AB CD EF  FE CC BA 98 76 54 32 10  .#Eg........vT2.

可以看到 这个数组对应的值,正好就是另外这个初始化变量的值(小端展示,需倒着看)

但是注意到有一个值是对应不上的 FE CC BA 98 76这里故意是将DC改成了CC, 所以相信直接用标准的Sha1算法计算出来的值,和这里的sha1算出来的值绝对是不一样的;

而在后续sub_19F0方法中我们找到了所有的K值,说明K是没有被魔改的

4. 编写frida看看,返回值是多少

function main() {
Java.perform(function () { var MainActivityHandler = Java.use('com.r0ysue.sha1.MainActivity') console.log('1111')
if (MainActivityHandler != undefined) {
console.log('2222' )
MainActivityHandler.sha1.implementation = function (str) {
console.log('hooked src str = ' + str)
var ret = this.sha1(str)
console.log('hooked ret = ' + ret) return ret
}
} }) } setTimeout(main, 1000)

日志

2222
hooked src str = abcd
hooked ret = 84fa69e00c65b500653e402ab42f9a2f26daa02c

通过在线sha1计算后的值是81fe8bfe87576c3ecb22426f8e57847382917acf

果然如我们所料,两个sha1的结果不一致

5. 编写python注册机,通过修改初始化常量值来匹配试试

#初始化变量
K = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6] A = 0x67452301
B = 0xEFCDAB89
C = 0x98BACCFE
D = 0x10325476
E = 0xC3D2E1F0 A0 = 0x67452301
B0 = 0xEFCDAB89
C0 = 0x98BACCFE
D0 = 0x10325476
E0 = 0xC3D2E1F0 '''字节转换,字节(8bit)->字(32bit)'''
def CharToWord( context,i):
return ((ord(context[i]) & 0x000000ff) << 24) | ((ord(context[i + 1]) & 0x000000ff) << 16) | ((ord(context[i + 2]) & 0x000000ff) << 8) | (ord(context[i + 3]) & 0x000000ff) '''填充补位获得原始明文'''
def SHA1_fill(plaintext, group, length):
print("补位后的明文:")
text1 = list(plaintext)
for n in range(length//8, 56):
text1.append(chr(0))
plaintext=''.join(text1)
temp = length // 32
len1 = length
while len1 > 0:
len1 = len1//32
if len1:
for j in range(0, temp):
group[j] = CharToWord(plaintext, 4 * j)
print(hex(group[j]))
else:
text = list(plaintext)
b = 0x80
text.insert(length // 8, chr(b))
plaintext = ''.join(text)
group[temp] = CharToWord(plaintext, temp * 4)
print(hex(group[temp]))
break
group[15] = length
for i in range(temp + 1,16):
print(hex(group[i]).ljust(10, '0')) '''f函数'''
def f(B ,C ,D , t):
if t >=0 and t <= 19:
return (B & C) ^ (~B & D)
if t >= 20 and t <= 39:
return B ^ C ^ D
if t >= 40 and t <= 59:
return (B & C) ^ (B & D) ^ (C & D)
if t >= 60 and t <= 79:
return B ^ C ^ D '''获得 Kt'''
def GETK(t):
if t >= 0 and t <= 19:
return K[0]
if t >= 20 and t <= 39:
return K[1]
if t >= 40 and t <= 59:
return K[2]
if t >= 60 and t <= 79:
return K[3] '''获得 Wt ,这里要特别注意mod(2**32)'''
def GETW(w):
for i in range(16,80):
w[i] = (((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]) << 1) | ((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]) >> 31)) % 2**32 '''步函数,注意mod(2**32)'''
def Step(t,w):
global A
global B
global C
global D
global E
T = (((A << 5) | (A >> 27)) + f(B, C, D, t) + E + w[t] + GETK(t)) % 2**32
E = D
D = C
C = ((B << 30) | (B >> 2)) % 2**32
B = A
A = T '''获得密文'''
def GetCipher(cipher):
cipher[0] = (A0 + A) % 2**32
cipher[1] = (B0 + B) % 2**32
cipher[2] = (C0 + C) % 2**32
cipher[3] = (D0 + D) % 2**32
cipher[4] = (E0 + E) % 2**32
print("密文为:")
for j in range(0, 5):
print(hex(cipher[j])[2:], end='')
print() def SHA1(context, cipher):
len1 = len(context) * 8
group = []
for i in range(80):
group.append(0)
SHA1_fill(context, group, len1)
GETW(group)
for t in range(80):
Step(t, group)
GetCipher(cipher) m = input("请输入长度小于56的明文:")
c = []
for i in range(0, 5):
c.append(0)
SHA1(m, c)
'''以下为python自带sha1函数,以便对照'''
import hashlib
print("自带函数哈希后密文:")
b = hashlib.sha1()
b.update(m.encode())
sha1 = b.hexdigest()
print(sha1)

日志

密文为:
84fa69e0c65b500653e402ab42f9a2f26daa02c
自带函数哈希后密文:
81fe8bfe87576c3ecb22426f8e57847382917acf

ok,成功对上,输入到手机爆破成功

【Android逆向】破解看雪9月算法破解第二题的更多相关文章

  1. off-by-one&doublefree. 看雪10月ctf2017 TSRC 第四题赛后学习

    off-by-one 0x00 发现漏洞 1.off-by-one 在massage函数中,如图所示,可以修改的字节数比原内存大小多了一个字节 2.悬挂指针 可以看到,在free堆块的时候,没有清空指 ...

  2. Android逆向之so的半自动化逆向

    因为工作需要,转型干android逆向,有几个月了.不过对于so的逆向,任然停留在,难难难的阶段,虽然上次自己还是逆向了一个15k左右的小so文件,但是,那个基本是靠,一步一步跟代码,查看堆栈信息来自 ...

  3. 天眼查sign 算法破解

    天眼查sign 算法破解 最近真的在sign算法破解上一去不复返 前几天看过了企查查的sign破解 今天再看看天眼查的sign算法破解,说的好(zhuang)点(bi)就是破解,不好的就是这是很简单的 ...

  4. Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)

    Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码) 来源 https://blog.csdn.net/jiangwei0910410003/article/details/51 ...

  5. Android 逆向实战篇(加密数据包破解)

    1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...

  6. 看雪论坛 破解exe 看雪CTF2017第一题分析-『CrackMe』-看雪安全论坛

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 逆向 黑客 破解 学习 论坛 『CrackMe』 http://bbs.pediy.co ...

  7. 启xin宝app的token算法破解——逆向篇(二)

    启xin宝app的token算法破解--抓包分析篇(一)文章已经对该app进行了抓包分析,现在继续对它进行逆向. 对于一个app而言,我们要逆向app,需要知道什么呢? 逆向工具 Java基础,甚至c ...

  8. Android逆向——破解水果大战

    最近公司需要测试安卓app安全,但安卓基本上0基础,决定开始学习下安卓逆向根据吾爱破解上教程 <教我兄弟学Android逆向系列课程+附件导航帖> https://www.52pojie. ...

  9. Android逆向破解表单注册程序

    Android逆向破解表单注册程序 Android开发 ADT: android studio(as) 程序界面如下,注册码为6位随机数字,注册成功时弹出通知注册成功,注册失败时弹出通知注册失败. 布 ...

  10. Android逆向破解表单登录程序

    Android逆向破解表单登录程序 Android开发 ADT: android studio(as) 程序界面如下,登录成功时弹出通知登录成功,登录失败时弹出通知登录失败. 布局代码 <?xm ...

随机推荐

  1. [转帖]kubernetes service 和 kube-proxy详解

    https://plantegg.github.io/2020/01/22/kubernetes%20service/ 性能情况.. service 模式 根据创建Service的type类型不同,可 ...

  2. [转帖]redis进程绑定指定的CPU核

    文章系转载,便于分类和归纳,源文地址:https://blog.csdn.net/youlinhuanyan/article/details/99671878 1)查看某服务的pid $ ps -au ...

  3. Nginx与Tomcat作为前端服务器的性能比较

    Nginx与Tomcat作为前端服务器的性能比较 摘要 最近总遇到使用tomcat还是使用nginx进行前端文件访问的争论 想着出差周末在酒店, 可以自己进行一下简单的测试. 希望能够对未来的工作进行 ...

  4. 【遇到一个怪异的问题】使用embed来加载模版,只要写在init()函数中就会导致HTTP服务出错

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 经过反复测试,只要换一个写法就能开启/重现这个怪异的问题. ...

  5. 自动部署(apb docker cicd gitlab)

    1.安装gitlab-runner docker pull gitlab/gitlab-runner:latest 2.运行镜像 docker run -d --name gitlab-runner ...

  6. 【一】MADDPG-单智能体|多智能体总结(理论、算法)

    相关文章: [一]MADDPG-单智能体|多智能体总结(理论.算法) [二]MADDPG--单智能体|多智能体总结算法实现--[追逐游戏] [一]-环境配置+python入门教学 [二]-Parl基础 ...

  7. 深度学习应用篇-推荐系统[11]:推荐系统的组成、场景转化指标(pv点击率,uv点击率,曝光点击率)、用户数据指标等评价指标详解

    深度学习应用篇-推荐系统[11]:推荐系统的组成.场景转化指标(pv点击率,uv点击率,曝光点击率).用户数据指标等评价指标详解 1. 推荐系统介绍 在网络技术不断发展和电子商务规模不断扩大的背景下, ...

  8. 【8】同步vscode配置和插件【导入导出】、再也不用担心换电脑重新安装插件了

    相关文章: [1]VScode中文界面方法-------超简单教程 [2]VScode搭建python和tensorflow环境 [3]VSCode 主题设置推荐,自定义配色方案,修改注释高亮颜色 [ ...

  9. ChatGPT 对接微信公众号技术方案实现!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 9天假期写了8天代码和10篇文章,这个5.1过的很爽! 如假期前小傅哥的计划一样,这个假期开启 ...

  10. 华为云DTSE助力车卫士架构升级,探索智能出行行业数字化新路径

    本文分享自华为云社区<华为云DTSE助力车卫士技术架构升级,探索智能出行行业数字化新路径>,作者:HuaweiCloudDeveloper. 毫无疑问,在双碳背景以及先进技术的加持下,智能 ...