吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2318|回复: 5
收起左侧

[Android 原创] luckfollowme arm学习篇 9 --在C内写arm介绍

  [复制链接]
2016976438 发表于 2023-5-1 12:32

luckfollowme arm学习篇 9 --在C内写arm介绍

这章是为了给 手写 inline Hook 做些准备的,要手写 inline hook  无非两种,

一种就像 dobby 那样插入字节码

  void EmitInt64(int64_t value) {
    buffer_->Emit64(value);
  }

还有一种就是 内联汇编 asm 或者 通过 gnu assembly

本次目标就是做到能够在 C内联 ARM

Inline ASM

Inline Assembly  一般来说 c/c++ 的编译器都自带 汇编编译器

最明显的关键字就是 asm

为了我们能够使用 asm  

您需要在 CMakeLists.txt 中加入:

# 启动支持 asm 汇编
enable_language(ASM)

asm 一般跟  volatile 一起使用,来告诉编译器编译的时候不要进行优化。

并且它还可以根据 输出操作数输入操作数 来跟 C/C++ 的变量进行交互

asm volatile("add %0,%1,%2":输出操作符:输入操作符1,输入操作符2)

组合起来就是这样:

int a = 100;
int b = 10;
int sum;
asm volatile("add %0,%1,%2":"=r"(sum):"r"(a),"r"(b)); # sum = a + b

其中 r 代表通用寄存器  =r 表示输出到的位置

下面是一个完整的例子:

首先您创建一个 AssemblyDemo.cpp

代码如下:

#include "stdio.h"
#include "stdint.h"

uint64_t _global_sum;

int sum(int a,int b){
    int _sum;
    asm volatile("add %w0 ,%w1,%w2":"=r"(_sum):"r"(a),"r"(b));
    return _sum;
}

int main()
{

    //1. 测试b 指令 死循环
    while (true)
    {
        int ret = sum(10,99);
        //3. 测试传参 和 调用方法
        printf("sum:%d\n",  ret);
        getchar();
    }
    return 0;
}

随后您修改 ndk_builder.pyCMakeLists.txt

# CMakeLists.txt
set(assmbly_demo1 
    ./source/AssemblyDemo1.cpp
)
add_executable(assmblyDemo1 ${assmbly_demo1})

记住,我们只测试 arm64 的,您应该修改 abis 否则 如果变成其他 arch 架构的平台 ,您写的汇编指令肯定是不通过的。

# abis = ["x86", "x86_64", "armeabi-v7a", "arm64-v8a"]
abis = ["arm64-v8a"]

编译出来后,我们拖入到 ida pro 静态分析一下:

</p>

01.png

</p>

可以看到 生成的 add 貌似并不是一条指令,这是正常的,因为它涉及到 读取和写入局部变量 也就是 输出操作符和输出操作符的位置

# 分配局部变量空间
SUB             SP, SP, #0x10
# 储存 x0-x1 的参数
STR             W0, [SP,#0xC]
STR             W1, [SP,#8]
# 读取 x0-x1 的参数
LDR             W8, [SP,#0xC]
LDR             W9, [SP,#8]
# a + b
ADD             W8, W8, W9
# _sum = a + b
STR             W8, [SP,#4]
# 读取 _sum 到 x0 准备返回值
LDR             W0, [SP,#4]
# 释放局部变量空间
ADD             SP, SP, #0x10
# 返回
RET

GAS

一般来说 写 gas 更方便一点,它的全称叫 GNU ASM

它里面有很多 Assembly Directive(汇编指示符) 来帮助我们编写各种格式的汇编

汇编指示符有点多,直接说长篇大论有点麻烦,也不容易理解,我们通过 将 原有代码 转换成 GAS 的汇编文件进行分析

为了分析的更方便,后面我都写成 .c 文件 而不是 .cpp

1.首先我们编写简单的HelloAssembly.c文件

#include <stdio.h>

int add(int a,int b){
    return a + b + 100;
}

int main(int argc, char const *argv[])
{
    while (1)
    {
        int a = 10;
        int b = 30;
        int sum = add(a,b);
        printf("sum:%d\n",sum);
        getchar();
    }

    /* code */
    return 0;
}

2.通过llvmaarch64交叉编译器转换成gas的汇编文件

aarch64 的教程编译器 我们使用clang 它位于 ndk 的

ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android21-clang.cmd

使用方式如下:

aarch64-linux-android21-clang -S 转换成assembly -o 输出位置 来源文件 

以下是我写的 arrch64-assembly.bat下的脚本:

C:\Users\hp\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android21-clang  -S -o ./helloassembly.S    HelloAssembly.c    

运行完您的 helloassmbly.S内容如下:

    .text
    .file   "HelloAssembly.c"
    .globl  add                             // -- Begin function add
    .p2align    2
    .type   add,@function
add:                                    // @add
    .cfi_startproc
// %bb.0:
    sub sp, sp, #16
    .cfi_def_cfa_offset 16
    str w0, [sp, #12]
    str w1, [sp, #8]
    ldr w8, [sp, #12]
    ldr w9, [sp, #8]
    add w8, w8, w9
    add w0, w8, #100
    add sp, sp, #16
    ret
.Lfunc_end0:
    .size   add, .Lfunc_end0-add
    .cfi_endproc
                                        // -- End function
    .globl  main                            // -- Begin function main
    .p2align    2
    .type   main,@function
main:                                   // @main
    .cfi_startproc
// %bb.0:
    sub sp, sp, #48
    stp x29, x30, [sp, #32]             // 16-byte Folded Spill
    add x29, sp, #32
    .cfi_def_cfa w29, 16
    .cfi_offset w30, -8
    .cfi_offset w29, -16
    stur    wzr, [x29, #-4]
    stur    w0, [x29, #-8]
    str x1, [sp, #16]
    b   .LBB1_1
.LBB1_1:                                // =>This Inner Loop Header: Depth=1
    mov w8, #10
    str w8, [sp, #12]
    mov w8, #30
    str w8, [sp, #8]
    ldr w0, [sp, #12]
    ldr w1, [sp, #8]
    bl  add
    str w0, [sp, #4]
    ldr w1, [sp, #4]
    adrp    x0, .L.str
    add x0, x0, :lo12:.L.str
    bl  printf
    bl  getchar
    b   .LBB1_1
.Lfunc_end1:
    .size   main, .Lfunc_end1-main
    .cfi_endproc
                                        // -- End function
    .type   .L.str,home.php?mod=space&uid=245521                  // @.str
    .section    .rodata.str1.1,"aMS",@progbits,1
.L.str:
    .asciz  "sum:%d\n"
    .size   .L.str, 8

    .ident  "Android (8490178, based on r450784d) clang version 14.0.6 (https://android.googlesource.com/toolchain/llvm-project 4c603efb0cca074e9238af8b4106c30add4418f6)"
    .section    ".note.GNU-stack","",@progbits

然后我们通过这个 .Sgas 汇编文件 通过 cmake 生成:

set(assmbly_gas_demo1
    ./source/assembly/helloassembly.S
)
add_executable(assmblygasdemo1 ${assmbly_gas_demo1})

您可以发现它依旧可以生成可执行程序。

也就是说我们可以通过 gas 汇编文件写出跟 c 一样的效果

汇编各位目前都看的懂吧,那么就差一点, gas 的 assembly directive 汇编助记符

下章我们将会逐步分析

免费评分

参与人数 6吾爱币 +13 热心值 +5 收起 理由
junjia215 + 1 + 1 用心讨论,共获提升!
正己 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
debug_cat + 2 + 1 用心讨论,共获提升!高产
Qwe95 + 1 我很赞同!
shuaibi_chen + 1 + 1 用心讨论,共获提升!
SPT + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

shuaibi_chen 发表于 2023-5-1 13:16
熟悉的汇编哈哈哈
moruye 发表于 2023-5-1 21:47
xuehailong 发表于 2023-5-2 07:14
debug_cat 发表于 2023-12-11 16:48
这里sum函数汇编需要知道申请函数空间,栈顶指针sub就是申请空间,add就是函数执行完恢复之前的lr返回上函数,中间就是取参数和做加法了
debug_cat 发表于 2023-12-11 16:51
debug_cat 发表于 2023-12-11 16:48
这里sum函数汇编需要知道申请函数空间,栈顶指针sub就是申请空间,add就是函数执行完恢复之前的lr返回上函 ...

这里错了,如果叶子函数是不会恢复lr,非叶子函数需要恢复现场,跑到上一个函数调用结束位置继续跑
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-26 06:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表