汇编&&虚拟机动态调试&&安卓逆向动态调试

[BJDCTF 2nd]8086

要先学一下汇编指令

这是一个直接看汇编的题(题目就是8086),因为XYCTF遇上了就去搜了一下

拖入exe啥也不知道,直接拖入ida看一下

啥也没有点进dseg看

汇编界面加注释是用“;”加点注释分析一下

 写出脚本得到flag

#include <stdio.h>
#include <string.h>
int main() 
{
    char a[] = "]U[du~|t@{z@wj.}.~q@gjz{z@wzqW~/b";
    
    int i;
	for (i=0;i<=strlen(a);i++)
	{
		a[i]^=31;
		
		printf("%c",a[i]);
	 } 

    return 0;
}//BJD{jack_de_hu1b1an_xuede_henHa0}

NKCTF-REEZ 

这道题用到了虚拟机和D-810去混淆

虚拟机:

现在ida中打开exe文件

1.虚拟机(先打开)

2.把ida里面的两个文件拖进去,在虚拟机桌面创建一个ida文件夹放入这两个文件

3.打开终端输入命令chmod 777 linux_server64(也可以直接将那个文件拖入)

4.继续输入命令.\linux_server64

5.重新开一个终端输入ifconfig命令

6.复制ip,放入框中的Hostname

想起来有之前培训的ppt(我懒)

D-810

对着数据去混淆

1.Edit->Plugins->D-810

2.出现这个界面然后点start,等一会儿回到之前的界面。按F5之后就可以去混淆了

之后大概就清晰很多了

题解

先拖入exe,发现是64位,然后拖入ida64,F5进入伪代码(什么也看不出来)

动态调试 之后会多出来一个文件,然后直接拖入ida

查看,应该是一个z3

去混淆,点start

 回到之前界面按F5就好了

 源码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  bool v3; // zf
  const char *v4; // rdi
  int v6; // [rsp+4h] [rbp-204h]
  __int64 v7; // [rsp+8h] [rbp-200h]
  char v8; // [rsp+17h] [rbp-1F1h]
  __int64 v9; // [rsp+18h] [rbp-1F0h]
  char *v10; // [rsp+20h] [rbp-1E8h]
  __int64 v11; // [rsp+28h] [rbp-1E0h]
  char v12; // [rsp+37h] [rbp-1D1h]
  __int64 v13; // [rsp+38h] [rbp-1D0h]
  __int64 v14; // [rsp+40h] [rbp-1C8h]
  __int64 v15; // [rsp+48h] [rbp-1C0h]
  __int64 v16; // [rsp+58h] [rbp-1B0h]
  __int64 j; // [rsp+70h] [rbp-198h]
  __int64 i; // [rsp+78h] [rbp-190h]
  __int64 v19[26]; // [rsp+80h] [rbp-188h]
  char v20; // [rsp+157h] [rbp-B1h] BYREF
  char v21; // [rsp+158h] [rbp-B0h] BYREF
  char v22; // [rsp+159h] [rbp-AFh] BYREF
  char v23; // [rsp+15Ah] [rbp-AEh] BYREF
  char v24; // [rsp+15Bh] [rbp-ADh] BYREF
  char v25; // [rsp+15Ch] [rbp-ACh] BYREF
  char v26; // [rsp+15Dh] [rbp-ABh] BYREF
  char v27; // [rsp+15Eh] [rbp-AAh] BYREF
  char v28; // [rsp+15Fh] [rbp-A9h] BYREF
  char v29; // [rsp+160h] [rbp-A8h] BYREF
  char v30; // [rsp+161h] [rbp-A7h] BYREF
  char v31; // [rsp+162h] [rbp-A6h] BYREF
  char v32; // [rsp+163h] [rbp-A5h] BYREF
  char v33; // [rsp+164h] [rbp-A4h] BYREF
  char v34; // [rsp+165h] [rbp-A3h] BYREF
  char v35; // [rsp+166h] [rbp-A2h] BYREF
  char v36; // [rsp+167h] [rbp-A1h] BYREF
  char v37; // [rsp+168h] [rbp-A0h] BYREF
  char v38; // [rsp+169h] [rbp-9Fh] BYREF
  char v39; // [rsp+16Ah] [rbp-9Eh] BYREF
  char v40; // [rsp+16Bh] [rbp-9Dh] BYREF
  char v41; // [rsp+16Ch] [rbp-9Ch] BYREF
  char v42; // [rsp+16Dh] [rbp-9Bh] BYREF
  char v43; // [rsp+16Eh] [rbp-9Ah] BYREF
  char v44[65]; // [rsp+16Fh] [rbp-99h] BYREF
  char v45[88]; // [rsp+1B0h] [rbp-58h] BYREF

  puts("D0_y0u_Like_What_You_See?");
  __isoc99_scanf("%25s", v45);
  v19[0] = (__int64)v44;
  v19[1] = (__int64)&v43;
  v19[2] = (__int64)&v42;
  v19[3] = (__int64)&v41;
  v19[4] = (__int64)&v40;
  v19[5] = (__int64)&v39;
  v19[6] = (__int64)&v38;
  v19[7] = (__int64)&v37;
  v19[8] = (__int64)&v36;
  v19[9] = (__int64)&v35;
  v19[10] = (__int64)&v34;
  v19[11] = (__int64)&v33;
  v19[12] = (__int64)&v32;
  v19[13] = (__int64)&v31;
  v19[14] = (__int64)&v30;
  v19[15] = (__int64)&v29;
  v19[16] = (__int64)&v28;
  v19[17] = (__int64)&v27;
  v19[18] = (__int64)&v26;
  v19[19] = (__int64)&v25;
  v19[20] = (__int64)&v24;
  v19[21] = (__int64)&v23;
  v19[22] = (__int64)&v22;
  v19[23] = (__int64)&v21;
  v19[24] = (__int64)&v20;
  for ( i = 0LL; i != 25; ++i )
    *(_BYTE *)v19[i] = v45[i];
  v44[0] = -105 * (39 * (v44[0] + -105 * (39 * (v33 + -105 * (39 * (v34 + 3) + 23) + 111) + 23) + 111) + 23) + 111;
  v43 = -105 * (39 * ((v31 ^ v30) + v43) + 23) + 111;
  v42 = -105 * (39 * (v42 + -105 * (39 * (v30 + v29) + 23) + 111) + 23) + 111;
  v41 = -105 * (39 * ((v27 ^ 0x17) + v41) + 23) + 111;
  v40 = -105 * (39 * (v40 + -105 * (39 * (v24 + -105 * (39 * (v35 - 5) + 23) + 111) + 23) + 111) + 23) + 111;
  v39 = -105 * (39 * (v39 + v23 - v21) + 23) + 111;
  v38 = -105 * (39 * (v38 + -105 * (39 * (v36 + v37) + 23) + 111) + 23) + 111;
  v37 = -105 * (39 * (v37 + -105 * (39 * (v21 - v24 + 17) + 23) + 111) + 23) + 111;
  v36 = -105 * (39 * (v36 + (v25 ^ (-105 * (39 * (v26 + 1) + 23) + 111))) + 23) + 111;
  v35 = -105 * (39 * (v27 + v35) + 23) + 111 - v28;
  v34 = -105 * (39 * (v34 + -105 * (39 * (v30 + v29) + 23) + 111) + 23) + 111;
  v33 = -105 * (39 * (v32 + -105 * (39 * (v31 + -105 * (39 * (v33 - 7) + 23) + 111) + 23) + 111) + 23) + 111;
  v32 = -105 * (39 * (v32 + v33) + 23) + 111;
  v31 = -105 * (39 * (v31 + (v37 ^ v36)) + 23) + 111;
  v30 = -105 * (39 * (v39 + -105 * (39 * (v40 + -105 * (39 * (v30 + 12) + 23) + 111) + 23) + 111) + 23) + 111;
  v29 = -105 * (39 * (v41 + -105 * (39 * (v29 + 8) + 23) + 111) + 23) + 111;
  v28 = -105 * (39 * ((v42 ^ 0x4D) + v28) + 23) + 111;
  v27 = -105 * (39 * (v27 + -105 * (39 * (2 * (v43 & 0xF9 ^ 0x11) + (v43 ^ 0xEE)) + 23) + 111) + 23) + 111;
  v26 = -105 * (39 * ((v27 ^ v29) + v26) + 23) + 111;
  v25 = -105 * (39 * (v32 + -105 * (39 * (v30 + v25) + 23) + 111) + 23) + 111;
  v24 = -105 * (39 * (v24 + v33) + 23) + 111;
  v23 = -105 * (39 * (v36 + -105 * (39 * (v23 + v38) + 23) + 111) + 23) + 111;
  v22 = -105 * (39 * (v39 + v22) + 23) + 111;
  v21 = -105 * (39 * ((v44[0] ^ v42) + v21) + 23) + 111;
  v20 = -105 * (39 * (v20 + -105 * (39 * (v43 + 24) + 23) + 111) + 23) + 111;
  for ( j = 0LL; j != 25; ++j )
  {
    v44[j + 1] = *(_BYTE *)v19[j];
    v14 = 0LL;
  }
  do
  {
    v15 = v14;
    v16 = 0LL;
    do
    {
      v9 = v16;
      v10 = &v44[5 * v14 + 33 + v16];
      *v10 = 0;
      v11 = 0LL;
      v12 = 0;
      do
      {
        v8 = -105 * (39 * (v12 + dword_2010[5 * v14 + v11] * v44[5 * v11 + 1 + v16]) + 23) + 111;
        v3 = v11++ == 4;
        v12 = v8;
      }
      while ( !v3 );
      *v10 = v8;
      ++v16;
    }
    while ( v9 != 4 );
    ++v14;
    v13 = 0LL;
  }
  while ( v15 != 4 );
  while ( 1 )
  {
    v7 = v13;
    if ( (byte_2080[v13] ^ (unsigned __int8)v44[v13 + 33]) != byte_20A0[v13] )
      break;
    ++v13;
    v6 = 25;
    if ( v7 == 24 )
      goto LABEL_19;
  }
  v6 = v13;
LABEL_19:
  v4 = "You are wrong!";
  if ( v6 == 25 )
    v4 = "What can I say? You are so great!";
  printf(v4);
  return 0;
}

rc4+z3

8086汇编算术指令

MOV赋值

MOV dest,src ;(dest)=(src)(就是把后一个的值赋给前一个)

立即数(Immediate)是指直接包含在指令中的常数或立即值。立即数通常用于执行特定的计算或操作,而不是从内存或寄存器中读取数据。

MOV指令可以完成的9操作:

  • 通用寄存器-->通用寄存器

  • 立即数-->通用寄存器

  • 立即数-->内存

  • 内存-->通用寄存器:MOV AX,DS:[BX]

  • 通用寄存器-->内存

  • 段寄存器(CS/IP除外)-->内存

  • 内存-->段寄存器(CS/IP除外)

  • 段寄存器(CS/IP除外)-->通用寄存器

  • 通用寄存器-->段寄存器(CS/IP除外)

注:MOV指令不能修改CS/IP的内容

不能直接把立即数放到段寄存器中

ADD假加法
ADD AX, BX     ; 加 AX 和 BX,结果存回 AX

加指令把右边的数加到左边的数中

其含义为(dest)=(dest)+(src)

可以完成的操作

  • ADD 通用寄存器,数据

  • ADD 通用寄存器,通用寄存器

  • ADD 通用寄存器,内存

  • ADD 内存,通用寄存器

  • ADD指令不能对段寄存器操作

ADC进位加

ADC CX, DX

加 CX 和 DX 以及前一个操作的进位,结果存回 CX

INC加一

INC AX ; 将寄存器 AX 中的值加一 INC [BX] ; 将存储在内存地址 BX 中的值加一

SUB减法
SUB AX, BX    ; 将寄存器 BX 中的值减去寄存器 AX 中的值,结果存入 AX
SUB [SI], DL  ; 将寄存器 DL 中的值减去存储在 SI 寄存器指向的内存位置中的值
​

减指令从左边的数中减去右边的数

可以完成的操作

  • SUB 通用寄存器,数据

  • SUB 通用寄存器,通用寄存器

  • SUB 通用寄存器,内存

  • SUB 内存,通用寄存器

SUB指令不能对段寄存器操作

DEC自减

它的功能与 INC 相反,是减少操作数的值。

DEC AX ; 将寄存器 AX 中的值减一 DEC [BX] ; 将存储在内存地址 BX 中的值减一

DIC除法

它将一个无符号的被除数除以一个无符号的除数,并将商存储在一个寄存器中,余数存储在另一个寄存器中。

MOV AX, 100 ; 被除数为 100 MOV DX, 0 ; 清空 DX,因为被除数是16位的,所以DX必须为0 MOV BX, 10 ; 除数为 10 DIV BX ; 执行除法操作,结果存储在 AX 中,余数存储在 DX 中

被除数/除数=商

除数:可以为8位或者16位,放在寄存器或者内存单元中,在指令的操作数中显式给出。

被除数:根据除数的位数动态调整:

  • 如果除数为8位,则被除数为16位,需提前放在AX中,不用在指令中给出

  • 如果除数为16位,则被除数为32位,需提前放在DX(高16位)、AX(低16位)中,不需要在指令中给出

商:

  • 如果除数为8位,则商将放到AL中,余数将放到AH中

  • 如果除数为16位,则商将放到AX中,余数将放到DX中

MUL乘法

它将一个无符号的乘数乘以另一个无符号的因数,并将结果存储在一个或多个寄存器中

MOV AX, 10    ; 被乘数为 10
MOV BX, 5     ; 乘数为 5
MUL BX        ; 执行乘法操作,结果存储在 AX 中
​
MUL REG/内存单元

两个数相乘,要么都是8位,要么都是16位。

如果是8位

  • 一个乘数需要提前放到AL中,无需在指令中给出

  • 另一个乘数可以放到8位寄存器或者内存单元中,需在指令中给出

  • 结果默认放到AX中

如果是16位

  • 一个乘数需要提前放到AX中,无需再指令中给出

  • 另一个乘数可以放到16位寄存器或者内存单元中,需在指令中给出

  • 结果默认高位放到DX中,低位放到AX中

CMP比较
CMP 对象1,对象2

执行对象对象对象1−对象2的运算,但不保留运算结果,只是根据运算结果对相应的标志寄存器进行置位

逻辑指令

AND、OR、NOT、XOR、TEST——与、或、非、异或等指令

  • AND AL,BL:将BL与AL的值进行按位与运算,结果存放到AL中

  • OR AL,BL:将BL与AL的值进行按位或运算,结果存放到BL中

  • XOR AL,BL:将BL与AL的值进行按位异或运算,结果存放到BL中

  • NOT AL:对AL各位取反,不改变标志寄存器的值

  • TEST AL,BL:将BL与AL的值进行按位与运算,不保存运算结果,只改变标志寄存器。

  • 两个操作数不能同时为内存单元,不能为段寄存器

  • 除了NOT,其他指令都会修改标志寄存器

8086汇编基础知识总结 - 知乎 (zhihu.com)

安卓动态调试

下载工具:jeb,雷电模拟器,apktool
文件操作步骤

最开始主要是路径问题,要把apktool和雷电模拟器里面的adb.exe文件添加到系统的路径里面去

1.

把apk文件和apktool放在一个文件夹里然后在上面的路径里输入cmd打开终端,输入这个,然后你的文件及里就会多出一个与apk文件同名的文件夹。apktool_2.9.3.jar 是我们下载的工具, 后面的 d 然后是你要拆包的apk

java -jar .\apktool_2.9.3.jar

.\apktool_2.9.3.jar d DebugMe.apk

这一步的作用是 拆包这个apk,会生成同名的文件夹,我们可以看到文件夹里的内容和我们一般通过开发工具或者apk后缀变为zip包后的文件差不多,这个就是拆包,然后删除签名文件 META-INF文件夹;在这个文件夹里你可以进行改动了;汉化,界面什么的

2

删除之后要更改新生成文件夹里面的AndroidManifest.xml,这个可以用记事本打开,主要就是要添加一个可调式信息(文件和包名主窗体,图片中打错字了后面有用,我最开始还不知道是什么)

android:debuggable="true"

删除签名文件程序打包成apk,-o 表示的是输出成test2.apk文件,这个DebugMe是我拆包的文件夹

java -jar .\apktool_2.9.3.jar b .\DebugMe\ -o test2.apk

然后给生成的apk文件签名

keytool -genkey -alias new.keystore -keyalg RSA -validity 20000 -keystore new.keystore

img

这个图不全我懒得截了,还要输入一个回车才是彻底结束


4

签名APK

未签名APK不能在安卓手机上安装,想要安装则想要对齐签名。

输入命令:

jarsigner -verbose -keystore new.keystore -signedjar test2_sign.apk test2.apk new.keystore

test2是我重打包之后的apk文件,需要给重打包后的text2文件进行签名

然后再输入密钥库的密码短语即你之前设置的密钥口令,即可签名

关于雷神模拟器
一.

先把adb有关的三个文件提出来组成一个新的文件夹然后添加到路径里去

二.

模拟器打开设置,找到开发者选项,打开usb调试

在雷电模拟器中打开 USB 调试功能需要先进入模拟器的设置界面,然后找到开发者选项,接着在开发者选项中启用 USB 调试。以下是一般情况下的步骤:

  1. 打开雷电模拟器。

  2. 在模拟器的主界面中,找到并点击设置图标(通常是一个齿轮状的图标,位于屏幕左上角或者右上角)。

  3. 进入设置界面后,向下滑动直到找到 "关于设备" 或 "关于手机",然后点击进入。

  4. 在 "关于设备" 或 "关于手机" 页面中,找到 "版本号" 或者 "版本信息",然后连续点击多次,直到提示开发者选项已启用。

  5. 返回上一级设置界面,你应该会在列表中看到一个新的选项 "开发者选项",点击进入。

  6. 在开发者选项界面中,向下滑动直到找到 "USB 调试" 选项。

  7. 启用 USB 调试功能,可能会有一个开关按钮或者复选框,根据提示进行操作即可。

启用后,你就可以通过 USB 连接模拟器,并在开发环境中调试应用程序了。需要注意的是,开启 USB 调试可能会涉及到安全风险,因此在使用完毕后记得及时关闭。

三.

在雷神模拟器下载apk文件,这里有一个很小的apk安装,选择你要下载的文件。

adb文件夹里输入连接口令

adb devices

连接成功之后会有端口出现

然后就是启动还是在终端继续输入

apkadb shell am start -D -n (包名)/(.主窗体)

这样差不多就是连接好了

4.用jeb打开文件夹最好是以管理员身份运行

然后连接雷电模拟器,记得把雷电模拟器的root打开,不然没办法调试

在 JEB 中设置断点通常涉及以下步骤:

  1. 加载应用程序:首先,您需要加载您想要调试的应用程序。这可以通过 JEB 的界面或命令行完成。

  2. 导航到目标代码:使用 JEB 的反编译器或其他工具,导航到您想要设置断点的代码位置。通常,您可以在反编译的代码中找到关键函数或方法。

  3. 设置断点:一旦找到要设置断点的位置,您可以在该位置上右键单击,在弹出菜单中选择“Toggle Breakpoint”(切换断点)或类似的选项来设置断点。您还可以使用快捷键来设置断点,通常是 F2。

  4. 运行调试器:一旦设置了断点,您可以运行调试器来启动应用程序。在调试模式下,当应用程序执行到设置的断点时,程序会暂停执行,您就可以在那里检查变量、调用栈等信息了。

  5. 处理断点:在应用程序执行到断点时,JEB 会提供一些选项来处理断点。您可以选择继续执行、单步执行、查看变量值等操作。

请注意,具体操作步骤可能会因 JEB 版本而有所不同,建议查阅 JEB 的官方文档以获取详细的操作指南。

  • 50
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值