某手新版本sig3参数算法还原

Frida Native层主动调用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

export function callDoCommandNative(){ // jni方法复习

    Java.perform(function() {

        var base_addr = Module.findBaseAddress("libkwsgmain.so") || ptr(0x0);

        var real_addr = base_addr.add(0x41680)

        var docommand = new NativeFunction(real_addr, "pointer", ["pointer""pointer""int""pointer"]);

        var JNIEnv = Java.vm.getEnv();

        var Intger = Java.use("java.lang.Integer");

        var jstring = Java.use("java.lang.String");

        var Boolean = Java.use("java.lang.Boolean");

        var cla = JNIEnv.findClass("java/lang/Object");

        // args1:,d7b7d042-d4f2-4012-be60-d97ff2429c17,,,com.yxcorp.gifshow.App@27101bb,,'} data: None

        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();

        var context = currentApplication.getApplicationContext();

        log("context"+context)

        var input_1 = JNIEnv.newStringUtf('d7b7d042-d4f2-4012-be60-d97ff2429c17');

        var argList_0 = JNIEnv.newObjectArray(7, cla, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList_0, 0, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList_0, 1, input_1);

        JNIEnv.setObjectArrayElement(argList_0, 2, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList_0, 3, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList_0, 4, context.$h);

        JNIEnv.setObjectArrayElement(argList_0, 5, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList_0, 6, ptr(0x0));

        var point_0 = docommand(JNIEnv, ptr(0x0), 10412, argList_0); // 返回的是指针,通过cast转成java对象,从而读出来

        console.log("point_0: " + point_0);

        var s_0 = Java.cast(point_0, Java.use("java.lang.Object"));

        console.log("result: " + s_0);

        var argList = JNIEnv.newObjectArray(8, cla, ptr(0x0));

        var argList_1 = JNIEnv.newObjectArray(1, cla, ptr(0x0));

        var input0 = JNIEnv.newStringUtf('/rest/n/feed/selectionbb9caf23ee1fda57a6c167198aba919f');

        var input1 = JNIEnv.newStringUtf('d7b7d042-d4f2-4012-be60-d97ff2429c17');

        var input2 = Boolean.$new(false);

        var input2_2 = Boolean.$new(false);

        var input3 = Intger.$new(-1);

        var input5 = JNIEnv.newStringUtf("010a11c6-f2cb-4016-887d-0d958aef1534");

         

        JNIEnv.setObjectArrayElement(argList_1, 0, input0);

        JNIEnv.setObjectArrayElement(argList, 0, argList_1);

        JNIEnv.setObjectArrayElement(argList, 1, input1);

        JNIEnv.setObjectArrayElement(argList, 2, input3.$h);

        JNIEnv.setObjectArrayElement(argList, 3, input2.$h);

        JNIEnv.setObjectArrayElement(argList, 4, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList, 5, ptr(0x0));

        JNIEnv.setObjectArrayElement(argList, 6, input2_2.$h);

        JNIEnv.setObjectArrayElement(argList, 7, input5);

        var point = docommand(JNIEnv, ptr(0x0), 10418, argList); // 返回的是指针,通过cast转成java对象,从而读出来

        var s = Java.cast(point, Java.use("java.lang.Object")); // $className : java.lang.String

        console.log("result: " + s);

        console.log("result: " + Java.vm.tryGetEnv().getStringUtfChars(point).readCString());

    })

}

     

export function jniOnload(){

    var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");

    if (android_dlopen_ext != null) {

        Interceptor.attach(android_dlopen_ext, {

            onEnter: function (args) {

                this.hook = false;

                var soName = args[0].readCString() || '';

                if (soName.indexOf("libkwsgmain.so") !== -1) {

                    this.hook = true;

                }

            },

            onLeave: function (retval) {

                if (this.hook) {

                    var jniOnload = Module.findExportByName("libkwsgmain.so""JNI_OnLoad") || ptr(0x0);

                    Interceptor.attach(jniOnload, {

                        onEnter: function (args) {

                            console.log("Enter Mtguard JNI OnLoad");

                        },

                        onLeave: function (retval) {

                            console.log("After Mtguard JNI OnLoad");

                            callDoCommandNative();

                            // hook_ks();

                        }

                    });

                }

            }

        });

    }

}

这里踩了一个坑,传入的对象数组里有个元素是context类型,打印出来是com.yxcorp.gifshow.App@b97f2c,所以想当然的就按这个类直接new了个对象传了进去,很快出现了报错:


这个报错让我百思不得其解,压根就没往context这块想,以为哪怕填个空指针都没问题的。

最后,用笨法frida hooknative层地址,打印定位,找到了如此地方:

此处判断X23的值是否为0,正常打印出来是/data/app/com.smile.gifmaker-q14Fo0PSb77vTIOM1-iEqQ==/base.apk,调用了getPackageCodePath 方法。 

这是一个context方法,那必须传入有效的context:

1

2

var currentApplication = Java.use("android.app.ActivityThread").currentApplication();

var context = currentApplication.getApplicationContext();

解决方法就是如此简单,基础,却让我绕了一大圈弯路,不得不感叹,基础真重要啊!

IDA静态分析

  • 花指令
    • 这块看龙哥的分析就好了,非常清晰

Unidbg模拟执行

  • 搭架子 & 补环境

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

package com.smile.gifmaker3;

import com.github.unidbg.*;

import com.github.unidbg.Module;

import com.github.unidbg.arm.backend.Backend;

import com.github.unidbg.arm.backend.CodeHook;

import com.github.unidbg.arm.backend.UnHook;

import com.github.unidbg.arm.backend.UnicornBackend;

import com.github.unidbg.arm.context.Arm32RegisterContext;

import com.github.unidbg.arm.context.Arm64RegisterContext;

import com.github.unidbg.file.FileResult;

import com.github.unidbg.file.IOResolver;

import com.github.unidbg.file.linux.AndroidFileIO;

import com.github.unidbg.linux.android.AndroidEmulatorBuilder;

import com.github.unidbg.linux.android.AndroidResolver;

import com.github.unidbg.linux.android.dvm.*;

import com.github.unidbg.linux.android.dvm.api.AssetManager;

import com.github.unidbg.linux.android.dvm.array.ArrayObject;

import com.github.unidbg.linux.android.dvm.wrapper.DvmBoolean;

import com.github.unidbg.linux.android.dvm.wrapper.DvmInteger;

import com.github.unidbg.memory.Memory;

import com.github.unidbg.pointer.UnidbgPointer;

import com.github.unidbg.spi.SyscallHandler;

import com.github.unidbg.utils.Inspector;

import com.github.unidbg.virtualmodule.android.AndroidModule;

import com.github.unidbg.virtualmodule.android.JniGraphics;

import com.sun.jna.Pointer;

import king.trace.GlobalData;

import king.trace.KingTrace;

import unicorn.Unicorn;

import unicorn.UnicornConst;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.PrintStream;

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.util.ArrayList;

import java.util.List;

public class kswgmain11420 extends AbstractJni implements IOResolver {

    private final AndroidEmulator emulator;

    private final VM vm;

    private final Module module;

    kswgmain11420() throws FileNotFoundException {

        // 创建模拟器实例,要模拟32位或者64位,在这里区分

        EmulatorBuilder<AndroidEmulator> builder = AndroidEmulatorBuilder.for64Bit().setProcessName("com.smile.gifmaker");

        emulator = builder.build();

        emulator.getSyscallHandler().setEnableThreadDispatcher(true);

        // 模拟器的内存操作接口

        final Memory memory = emulator.getMemory();

        // 设置系统类库解析

        memory.setLibraryResolver(new AndroidResolver(23));

        // 创建Android虚拟机

        // vm = emulator.createDalvikVM();

        vm = emulator.createDalvikVM(new File("unidbg-android\\src\\test\\java\\com\\smile\\gifmaker3\\1142064wei.apk"));

        // 设置是否打印Jni调用细节

        vm.setVerbose(true);

        new JniGraphics(emulator, vm).register(memory);

        new AndroidModule(emulator, vm).register(memory);

        vm.setJni(this);

        SyscallHandler<AndroidFileIO> handler = emulator.getSyscallHandler();

        handler.addIOResolver(this);

        // 加载libttEncrypt.so到unicorn虚拟内存,加载成功以后会默认调用init_array等函数

        DalvikModule dm = vm.loadLibrary(new File("unidbg-android\\src\\test\\java\\com\\smile\\gifmaker3\\libkwsgmain.so"), true);

        // 加载好的libttEncrypt.so对应为一个模块

        module = dm.getModule();

        // trace code

//        String traceFile = "unidbg-android\\src\\test\\java\\com\\smile\\gifmaker3\\sig3_jniOnload.trc";

//        GlobalData.ignoreModuleList.add("libc.so");

//        GlobalData.ignoreModuleList.add("libhookzz.so");

//        GlobalData.ignoreModuleList.add("libc++_shared.so");

//        emulator.traceCode(module.base, module.base+module.size).setRedirect(new PrintStream(new FileOutputStream(traceFile), true));

        dm.callJNI_OnLoad(emulator);

    }

    public static void main(String[] args) throws FileNotFoundException {

        kswgmain11420 kk = new kswgmain11420();

        kk.init_native();

        kk.get_NS_sig3();

    }

    public void init_native() throws FileNotFoundException {

        // trace code

//        String traceFile = "unidbg-android\\src\\test\\java\\com\\smile\\gifmaker3\\sig3_init_native.trc";

//        GlobalData.ignoreModuleList.add("libc.so");

//        GlobalData.ignoreModuleList.add("libhookzz.so");

//        GlobalData.ignoreModuleList.add("libc++_shared.so");

//        emulator.traceCode(module.base, module.base+module.size).setRedirect(new PrintStream(new FileOutputStream(traceFile), true));

        List<Object> list = new ArrayList<>(10);

        list.add(vm.getJNIEnv()); // 第一个参数是env

        DvmObject<?> thiz = vm.resolveClass("com/kuaishou/android/security/internal/dispatch/JNICLibrary").newObject(null);

        list.add(vm.addLocalObject(thiz)); // 第二个参数,实例方法是jobject,静态方法是jclass,直接填0,一般用不到。

        DvmObject<?> context = vm.resolveClass("com/yxcorp/gifshow/App").newObject(null); // context

        vm.addLocalObject(context);

        list.add(10412); //参数1

        StringObject appkey = new StringObject(vm,"d7b7d042-d4f2-4012-be60-d97ff2429c17"); // SO文件有校验

        vm.addLocalObject(appkey);

        DvmInteger intergetobj = DvmInteger.valueOf(vm, 0);

        vm.addLocalObject(intergetobj);

        list.add(vm.addLocalObject(new ArrayObject(intergetobj,appkey,intergetobj,intergetobj,context,intergetobj,intergetobj)));

        // 直接通过地址调用

        Number numbers = module.callFunction(emulator, 0x41680, list.toArray());

        System.out.println("numbers:"+numbers);

        DvmObject<?> object = vm.getObject(numbers.intValue());

        String result = (String) object.getValue();

        System.out.println("result:"+result);

    }

    @Override

    public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {

        switch (signature) {

            case "com/yxcorp/gifshow/App->getPackageCodePath()Ljava/lang/String;": {

                return new StringObject(vm, "/data/app/com.smile.gifmaker-q14Fo0PSb77vTIOM1-iEqQ==/base.apk");

            }

            case "com/yxcorp/gifshow/App->getAssets()Landroid/content/res/AssetManager;": {

//                return new Long(vm, "3817726272");

                return new AssetManager(vm, signature);

            }

            case "com/yxcorp/gifshow/App->getPackageName()Ljava/lang/String;": {

                return new StringObject(vm, "com.smile.gifmaker");

            }

            case "com/yxcorp/gifshow/App->getPackageManager()Landroid/content/pm/PackageManager;": {

                DvmClass clazz = vm.resolveClass("android/content/pm/PackageManager");

                return clazz.newObject(signature);

            }

        }

        return super.callObjectMethodV(vm, dvmObject, signature, vaList);

    }

    @Override

    public boolean callBooleanMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {

        switch (signature) {

            case "java/lang/Boolean->booleanValue()Z":

                DvmBoolean dvmBoolean = (DvmBoolean) dvmObject;

                return dvmBoolean.getValue();

        }

        return super.callBooleanMethodV(vm, dvmObject, signature, vaList);

    }

    public String get_NS_sig3() throws FileNotFoundException {

        // trace code

//        String traceFile = "unidbg-android\\src\\test\\java\\com\\smile\\gifmaker3\\sig3_new.trc";

//        GlobalData.ignoreModuleList.add("libc.so");

//        GlobalData.ignoreModuleList.add("libhookzz.so");

//        GlobalData.ignoreModuleList.add("libc++_shared.so");

//        emulator.traceCode(module.base, module.base+module.size).setRedirect(new PrintStream(new FileOutputStream(traceFile), true));

        System.out.println("_NS_sig3 start");

        List<Object> list = new ArrayList<>(10);

        list.add(vm.getJNIEnv()); // 第一个参数是env

        DvmObject<?> thiz = vm.resolveClass("com/kuaishou/android/security/internal/dispatch/JNICLibrary").newObject(null);

        list.add(vm.addLocalObject(thiz)); // 第二个参数,实例方法是jobject,静态方法是jclass,直接填0,一般用不到。

        DvmObject<?> context = vm.resolveClass("com/yxcorp/gifshow/App").newObject(null); // context

        vm.addLocalObject(context);

        list.add(10418); //参数1

        StringObject urlObj = new StringObject(vm, "/rest/app/eshop/ks/live/item/byGuest6bcab0543b7433b6d0771892528ef686");

        vm.addLocalObject(urlObj);

        ArrayObject arrayObject = new ArrayObject(urlObj);

        StringObject appkey = new StringObject(vm,"d7b7d042-d4f2-4012-be60-d97ff2429c17");

        vm.addLocalObject(appkey);

        DvmInteger intergetobj = DvmInteger.valueOf(vm, -1);

        vm.addLocalObject(intergetobj);

        DvmBoolean boolobj = DvmBoolean.valueOf(vm, false);

        vm.addLocalObject(boolobj);

        StringObject appkey2 = new StringObject(vm,"7e46b28a-8c93-4940-8238-4c60e64e3c81");

        vm.addLocalObject(appkey2);

        list.add(vm.addLocalObject(new ArrayObject(arrayObject,appkey,intergetobj,boolobj,context,null,boolobj,appkey2)));

        // 直接通过地址调用

        Number numbers = module.callFunction(emulator, 0x41680, list.toArray());

        System.out.println("numbers:"+numbers);

        DvmObject<?> object = vm.getObject(numbers.intValue());

        String result = (String) object.getValue();

        System.out.println("result:"+result);

        return result;

    }

    @Override

    public FileResult resolve(Emulator emulator, String pathname, int oflags) {

        System.out.println("fuck:"+pathname);

        return null;

    }

    public String readStdString(Pointer strptr){

        Boolean isTiny = (strptr.getByte(0) & 1) == 0;

        if(isTiny){

            return strptr.getString(1);

        }

        return strptr.getPointer(emulator.getPointerSize()* 2L).getString(0);

    }

    @Override

    public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {

        switch (signature) {

            case "com/kuaishou/android/security/internal/common/ExceptionProxy->getProcessName(Landroid/content/Context;)Ljava/lang/String;":

                return new StringObject(vm, "com.smile.gifmaker");

            case "com/meituan/android/common/mtguard/NBridge->getSecName()Ljava/lang/String;":

                return new StringObject(vm, "ppd_com.sankuai.meituan.xbt");

            case "com/meituan/android/common/mtguard/NBridge->getAppContext()Landroid/content/Context;":

                return vm.resolveClass("android/content/Context").newObject(null);

            case "com/meituan/android/common/mtguard/NBridge->getMtgVN()Ljava/lang/String;":

                return new StringObject(vm, "4.4.7.3");

            case "com/meituan/android/common/mtguard/NBridge->getDfpId()Ljava/lang/String;":

                return new StringObject(vm, "");

        }

        return super.callStaticObjectMethodV(vm, dvmClass, signature,vaList);

    }

}

这里也有一个小tips,让unidbg加载指定SO文件,如果这个SO有依赖其他的SO库,那么很有可能会加载失败。这个情况不同于直接加载apk文件里的so文件,那种情况下unidbg会帮我们自动去寻找需要的SO文件。这个情况下,我们只要把需要的SO文件提取出来,放在同一目录下即可。

  • trace code

    用去花后的so文件,trace关键函数,很快的。

SHA256还原

结合ida伪代码和sha256的伪代码,还原

  • 思路:先看iv和table,然后看明文编排,最后比对具体运算 ———— 龙哥语录
  • sha256算法基础

确定调用栈

  • [确定调用堆栈]
  • 找到sig3最先出现的地方
  • sub_2636c 编排地址:

 

  • sub_2BD20
  • sub_25938
  • sub_120C4

至此,明文输入字符串的加密结果拿到

拼接过程

  • 固定字符串
  • 随机字符串
    • 猜测是随机,进一步验证,追踪,在JNI_OnLoad里:
  • 明文字符加密结果
  • 时间戳
  • 固定字符串

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/139588.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Lua学习笔记:探究package

前言 本篇在讲什么 理解Lua的package 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级…

ruoyi框架修改左侧菜单样式

菜单效果 ruoyi前端框架左侧的菜单很丑&#xff0c;我们需要修改一下样式&#xff0c;下面直接看效果。 修改代码 1、sidebar.scss .el-menu-item, .el-submenu__title {overflow: hidden !important;text-overflow: ellipsis !important;white-space: nowrap !important;//…

微软宣布推广数字助理 Copilot;GPT 应用开发和思考

&#x1f989; AI新闻 &#x1f680; 微软宣布推广基于生成式人工智能的数字助理 Copilot 摘要&#xff1a;微软宣布将基于生成式人工智能的数字助理 Copilot 推广到更多软件产品中。新的 AI 助理 Microsoft Copilot 将在 Windows 中无缝可用&#xff0c;包括 Windows 11 桌面…

【C++面向对象侯捷】12.虚函数与多态 | 13.委托相关设计【设计模式 经典做法,类与类之间关联起来,太妙了,不断的想,不断的写代码】

文章目录 12.虚函数与多态举例&#xff1a;委托 继承【观察者模式】13.委托相关设计Composite 组合模式Prototype 原型模式 12.虚函数与多态 纯虚函数 一定要 子类重新定义的 继承和复合 关系下的构造和析构 举例&#xff1a;委托 继承【观察者模式】 13.委托相关设计 问题…

BOM与DOM--记录

BOM基础&#xff08;BOM简介、常见事件、定时器、this指向&#xff09; BOM和DOM的区别和联系 JavaScript的DOM与BOM的区别与用法详解 DOM和BOM是什么&#xff1f;有什么作用&#xff1f; 图解BOM与DOM的区别与联系 BOM和DOM详解 JavaScript 中的 BOM&#xff08;浏览器对…

蓝桥杯 题库 简单 每日十题 day8

01 扫雷 题目描述 在一个n行列的方格图上有一些位置有地雷&#xff0c;另外一些位置为空。 请为每个空位置标一个整数&#xff0c;表示周围八个相邻的方格中有多少个地雷。 输入描述 输入的第一行包含两个整数n&#xff0c;m。 第2行到第n1行每行包含m个整数&#xff0c;相邻整…

数据结构——单链表

目录 一.前言 二.链表表示和实现&#xff08;单链表&#xff09; 1.1 顺序表的优缺点 1.2 链表的概念及结构 1.3 打印函数 1.4 空间函数 1.5 尾插函数&#xff08;最最最麻烦的&#xff09; 1.5.1 尾插最关键部分&#xff01; 1.6 头插函数 1.7 尾删函数…

深拷贝和浅拷贝

两者区别 深拷贝和浅拷贝是用来描述对象或者对象数组这种引用数据类型的复制场景的。 浅拷贝 浅拷贝&#xff0c;就是只复制某个对象的指针&#xff0c;而不复制对象本身。这种复制方式意味着两个引用指针指向被复制对象的同一块内存地址&#xff0c;如下图&#xff1a; 深拷贝…

conda的安装和使用

参考资料&#xff1a; https://www.bilibili.com/read/cv8956636/?spm_id_from333.999.0.0 https://www.bilibili.com/video/BV1Mv411x775/?spm_id_from333.999.0.0&vd_source98d31d5c9db8c0021988f2c2c25a9620 目录 conda是啥以及作用conda的安装conda的启动conda的配置…

git和github的入门操作

之前因为工作中用的都是SVN版本控制工具&#xff0c;没接触过git和github&#xff0c;现在开始深入自学Django框架技术后&#xff0c;看到官网推荐使用git&#xff0c;然后这两天网上查阅了很多文章教程&#xff0c;学到入门操作需要学习的点&#xff0c;太多的知识点要后面慢慢…

多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出

多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出 目录 多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | MATLAB实现GA-BP遗传算法优化BP神经网络多输入多输出…

接入国家能源平台MQTT应用案例

一、项目介绍 随着国家对节能环保措施的力度不断加大&#xff0c;基于物联网技术搭建的国家能源平台在国家相关部门的建设下逐渐成熟。致力于利用实际能耗数据建立能效仿真模型&#xff0c;通过实时寻优运算&#xff0c;获得当前的最优化运行策略&#xff0c;并将控制指令下发…

MDK工程转换Vscode+EIDE方法

MDK工程转换VscodeEIDE方法 1、VscodeEIDE环境搭建方法 请按下方视频完成环境搭建&#xff0c;并编译成功。下载&#xff0c;单步调试如无视频中芯片可暂不执行。 https://www.bilibili.com/video/BV1Zu4y1f72H/?spm_id_from333.337.search-card.all.click&vd_source73…

摩尔信使MThings实用功能盘点

“冗长的用户手册”与“精简的交互设计”之间势必产生一条信息鸿沟&#xff0c;现在就来盘点一下摩尔信使MThings有哪些隐蔽而实用的功能。 01 数据配置类 一键刷新 功能&#xff1a;快速读取所有位数据、寄存器数据的当前数值。 操作&#xff1a;双击“数值”列表头。 一键…

有一个新工具,能让程序员变成高手,优雅撸它!

不知道从什么时候开始&#xff0c;程序员这个职位变得家喻户晓&#xff0c;对程序员的印象也从以前的高深莫测变成如今的加班代名词。对于程序员加班&#xff0c;不懂有话要说。 作为大厂的一枚螺丝钉&#xff0c;接到任务的第一时间需要缕清底层逻辑&#xff0c;并随时关注部门…

AUTOSAR实战篇:手把手带你搞定Watchdog协议栈

AUTOSAR实战篇:手把手带你搞定Watchdog协议栈 前言 小T出品,必是精品! 手把手搞定Watchdog协议栈,你值得拥有! 正文 在进行Watchdog协议栈实战之前,建议先阅读小T之前有关Watchdog协议栈的两篇文章《Watchdog协议栈上》与《Watchdog协议栈下》先了解下在AUTOSAR框架下的W…

SQL模板-用户留存率计算

在这段实习中&#xff0c;我遇到了用户留存率计算的需求&#xff0c;这里做个总结。 首先来讲下&#xff0c;什么是用户留存&#xff1f; 在互联网行业中&#xff0c;用户在某段时间内开始使用应用&#xff0c;经过一段时间后&#xff0c;仍然继续使用该应用的用户。用户留存一…

【数据分享】2005-2022年全国民航机场客货吞吐量和起降架次数据

机场是一个城市对外联系的重要渠道&#xff0c;机场的旅客吞吐量和货物吞吐量是体现一个城市对外联系程度的重要指标。 本次我们给大家分享的是2005-2022年我国民航机场的旅客吞吐量、货邮吞吐量、起降架次数据。数据格式为Excel和Shp两种格式。数据坐标为WGS1984。原始数据来…

根据条件关闭软件

使用下载工具时&#xff0c;经常出现磁盘空间已满&#xff0c;无法下载的情况。 使用shell写一个监控&#xff0c;每2分钟执行一次。判断当前磁盘的空间&#xff0c;低于2G时&#xff0c;关闭下载软件。 获取空间大小 ➜ ~ df -h …

CTF--攻防世界杂项--第二课

下载题目根据文件类型可知&#xff0c;这是一个流量包 那么接下来就是利用分析流量包常用的工具wireshark来分析 利用关键词进行搜索 http contains shell 在最后一条数据中看到了flag。 以上就结束&#xff0c;非常简单的一道题。