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

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2319|回复: 7
收起左侧

[Android 原创] luckfollowme arm学习篇(10) ---- Gas Directive

  [复制链接]
2016976438 发表于 2023-5-4 13:16
本帖最后由 2016976438 于 2023-5-4 13:17 编辑

luckfollowme arm学习篇(10) ---- Gas Directive

这篇主要是理解 gas assembly 指令指示符。 并手写 gas 汇编文件并与 c/c++ 交互

(感谢大家支持,我的被标记精华了,哈哈哈~)
大概在有几章就结束了,没有啥资料可以学了。

gas 指令指示符

我们修改上一章的代码,在之前的代码中 加入 全局变量 。

#include <stdio.h>
#include "stdint.h"

// 测试全局变量 的 int64 和 string 类型
uint64_t glob_num = 100;
const char* glob_str = "sum:%d\n";

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

int main(int argc, char const *argv[])
{
    while (1)
    {
        int a = 10;
        int b = 30;
        int sum = add(a,b);
        printf(glob_str,sum);
        getchar();
    }

    /* code */
    return 0;
}

生成 assembly

        .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        w9, w8, w9
        adrp        x8, glob_num
        ldr        x8, [x8, :lo12:glob_num]
        add        x8, x8, w9, sxtw
        mov        w0, w8
        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]
        adrp        x8, glob_str
        ldr        x0, [x8, :lo12:glob_str]
        ldr        w1, [sp, #4]
        bl        printf
        bl        getchar
        b        .LBB1_1
.Lfunc_end1:
        .size        main, .Lfunc_end1-main
        .cfi_endproc
                                        // -- End function
        .type        glob_num,home.php?mod=space&uid=245521                // @glob_num
        .data
        .globl        glob_num
        .p2align        3
glob_num:
        .xword        100                             // 0x64
        .size        glob_num, 8

        .type        .L.str,@object                  // @.str
        .section        .rodata.str1.1,"aMS",@progbits,1
.L.str:
        .asciz        "sum:%d\n"
        .size        .L.str, 8

        .type        glob_str,@object                // @glob_str
        .data
        .globl        glob_str
        .p2align        3
glob_str:
        .xword        .L.str
        .size        glob_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

debug 信息

在生成的 assembly 中,经过我的测试,有几项指令应该是 用于调试 debug 使用的

.file 指令 应该表示汇编的文件

.cfi_指令cfi_ 开头的指令貌似用于描述 stack frame 栈帧信息,比较常见的就是

.cfi_startproc 方法的开始

.cfi_endproc 方法的结束

.cfi_def_cfa_offset 栈偏移

.cfi_endproc 栈结束

.section 描述段信息

.ident 构建信息

当然我测过了的,它们可以删除,删除后的样子如下:

        .text
        .globl        add                             // -- Begin function add
        .p2align        2
        .type        add,@function
add:                                    // @add
// %bb.0:
        sub        sp, sp, #16
        str        w0, [sp, #12]
        str        w1, [sp, #8]
        ldr        w8, [sp, #12]
        ldr        w9, [sp, #8]
        add        w9, w8, w9
        adrp        x8, glob_num
        ldr        x8, [x8, :lo12:glob_num]
        add        x8, x8, w9, sxtw
        mov        w0, w8
        add        sp, sp, #16
        ret
.Lfunc_end0:
        .size        add, .Lfunc_end0-add
                                        // -- End function
        .globl        main                            // -- Begin function main
        .p2align        2
        .type        main,@function
main:                                   // @main
// %bb.0:
        sub        sp, sp, #48
        stp        x29, x30, [sp, #32]             // 16-byte Folded Spill
        add        x29, sp, #32
        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]
        adrp        x8, glob_str
        ldr        x0, [x8, :lo12:glob_str]
        ldr        w1, [sp, #4]
        bl        printf
        bl        getchar
        b        .LBB1_1
.Lfunc_end1:
        .size        main, .Lfunc_end1-main
                                        // -- End function
        .type        glob_num,@object                // @glob_num
        .data
        .globl        glob_num
        .p2align        3
glob_num:
        .xword        100                             // 0x64
        .size        glob_num, 8

        .type        .L.str,@object                  // @.str
.L.str:
        .asciz        "sum:%d\n"
        .size        .L.str, 8

        .type        glob_str,@object                // @glob_str
        .data
        .globl        glob_str
        .p2align        3
glob_str:
        .xword        .L.str
        .size        glob_str, 8

add

我们先来分析 add 方法 以及它用到的指令

截取出来是这样的

        .text
        .globl        add                             // -- Begin function add
        .p2align        2
        .type        add,@function
add:                                    // @add
// %bb.0:
        sub        sp, sp, #16
        str        w0, [sp, #12]
        str        w1, [sp, #8]
        ldr        w8, [sp, #12]
        ldr        w9, [sp, #8]
        add        w9, w8, w9
        adrp        x8, glob_num
        ldr        x8, [x8, :lo12:glob_num]
        add        x8, x8, w9, sxtw
        mov        w0, w8
        add        sp, sp, #16
        ret
.Lfunc_end0:
        .size        add, .Lfunc_end0-add        

我们依次从上往下分析

text section

.text 表示代码开始的 代码段

global symbol

.global 代表声明全局符号 可提供外部使用

.globl        add    代表定义 add 的全局symbol

p2align

表示内存对齐

p2align        2 表示对齐 2*2 = 4 字节的内存

.type

定义符号类型

.type        add,home.php?mod=space&uid=1435519表示 add symbol 是一个 方法

add arm

接下来是分析 当中的 arm 汇编。里面存在 伪指令引用 全局符号 glob_num 看我的注释意思即可

add:                                  
        # 开辟局部变量的栈空间
        sub        sp, sp, #16
        # 将 a 和 b 的参数 放入 栈空间
        str        w0, [sp, #12]
        str        w1, [sp, #8]
        # 获取 a 和 b
        ldr        w8, [sp, #12]
        ldr        w9, [sp, #8]
        # a + b
        add        w9, w8, w9
        # 伪指令 获取基于 pc + glob_num 的 4kb 内存页对齐 
        adrp        x8, glob_num
        #  :lo12: 表示取 低12位内的glob_num地址  也就是4kb内的偏移
        ldr        x8, [x8, :lo12:glob_num]
        # 将 glob_num + a + b  (sxtw 表示 x8 转 w8 也就是 word 32 位)
        add        x8, x8, w9, sxtw
        # 剩下就是 返回值 和 恢复栈了
        mov        w0, w8
        add        sp, sp, #16
        ret

对应 c 的代码:

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

方法结束

.Lfunc_end0: 表示结束方法的标签,这个标签名字可以自定义

.size 表示这个方法的大小

.Lfunc_end0:
        # add 方法的大小 = Lfunc_end0 - add开始地址
        .size        add, .Lfunc_end0-add

main

至于 main 方法 指令都见过,我就直接分析了

        # 定义main symbol
        .globl        main                            // -- Begin function main
        # 4 字节 内存对齐
        .p2align        2
        # main symbol 类型是 方法 
        .type        main,@function
main:                                   // @main
        # 分配栈空间
        sub        sp, sp, #48
        # x29(FP) x30(LR) 入栈 方法结束时候恢复
        stp        x29, x30, [sp, #32]             // 16-byte Folded Spill
        # 表示 x29 以栈低开始
        add        x29, sp, #32
        # wzr(zero) 用于清零 [x29 - 4] = 0
        stur        wzr, [x29, #-4]
        # [x29 -8] = w0
        stur        w0, [x29, #-8]
        # [sp + 16] = x1
        str        x1, [sp, #16]
        # 跳入死循环
        b        .LBB1_1
.LBB1_1:                                // =>This Inner Loop Header: Depth=1
        # a = 10
        mov        w8, #10
        str        w8, [sp, #12]
        # b = 30
        mov        w8, #30
        str        w8, [sp, #8]
        # add方法 传参 a  b 
        ldr        w0, [sp, #12]
        ldr        w1, [sp, #8]
        # 调用 add
        bl        add
        # w0 = 返回值
        str        w0, [sp, #4]
        # 获取 glob_str 4kb 内存页地址
        adrp        x8, glob_str
        # printf方法 传参 
        # 获取 glob_str 低12(4kb 内) 位的偏移
        ldr        x0, [x8, :lo12:glob_str]
        # add方法 返回值
        ldr        w1, [sp, #4]
        bl        printf
        bl        getchar
        # 重复循环
        b        .LBB1_1
.Lfunc_end1:
        # main 方法结束 size = Lfunc_end1-main
        .size        main, .Lfunc_end1-main

全局变量

定义全局变量一般格式为:

        # 符号类型为 @object        
        .type        符号,@object        
        # 数据段 还有一个就是 text 代码段
        .data
        # 全局符号
        .globl        glob_num
        # 内存对齐 看数据长度
        .p2align        3

glob_num

        # glob_num 符号是 对象类型
        .type        glob_num,@object                // @glob_num
        # 数据段
        .data
        # 定义 glob_num 全局符号
        .globl        glob_num
        # 2^3 = 8 字节内存对齐
        .p2align        3

        # glob_num 符号的数据定义
glob_num:
        # 使用 64 位 整数 值是 100 
        # 当然还有 个 word 是 32位
        .xword        100                             // 0x64
        # 数据大小是 8字节
        .size        glob_num, 8

glob_str

这个比较麻烦了,因为它是个字符串。

# 定义本地标签数据段 不会被外部引用
.L.str:
        # ascii 字符串数据
        .asciz        "sum:%d\n"
        # 长度是8
        .size        .L.str, 8

    # 定于 glob_str 符号类型是 @object 
        .type        glob_str,@object                // @glob_str
        # 数据段
        .data
        # 全局 symol
        .globl        glob_str
        # 8 字节对齐
        .p2align        3
glob_str:
        # 引用 .L.str 数据
        .xword        .L.str
        #  长度是 8
        .size        glob_str, 8

到这里分析就差不多了。接下来我们就尝试手动写 add assembly 方法,并提供给 c/c++ 使用

手写 gas 文件

为了方便,您先下载 gnu assembler 插件 可以帮助您完成部分 intellSence

首先我创建一个 assembly_add.S 的 gas 汇编文件

并写入 add 方法的汇编

    .text
    .globl add
    .p2align 2
    .type add,@function
add:
    sub sp,sp,#16
    // 第一个参数
    str w0,[sp,#12]
    // 第二个参数
    str w1,[sp,#8]
    ldr w0,[sp,#12]
    ldr w1,[sp,#8]
    // a + b
    add w0,w0,w1
    // 还原栈
    add sp,sp,#16        
    ret
.Lfunc_end0:
    //方法结束 size = 当前 - add
    .size add, .-add    

在写个 assembly_add_demo1.cpp

#include "stdio.h"

// extern C 表示方法是标准C的
// 且 方法是从外部链接过来的
extern "C"{
    int add(int a,int b);
}
int main(int argc, char const *argv[])
{

    int a = 99;
    int b = 1;

    int ret = add(a,b);
    printf("ret:%d",ret);
    return 0;
}

接下来在 CMakeLists.txt 中加入如下片段:

set(assmbly_add_demo1
    ./source/assembly/assembly_add.S
    ./source/assembly/aseembly_add_demo1.cpp
)

# 测试 gas 汇编文件与 c++ 交互
add_executable(assmbl-add-demo1 ${assmbly_add_demo1})

然后修改 ndb_builder.pyadb_execute_arm64.bat 方法进行构建和运行

至此,您已经会 如何在 c/c++ 中写 arm

下一章就开始讲解手写 inline hook

免费评分

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

查看全部评分

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

debug_cat 发表于 2023-5-4 15:38
学习进度跟不上了
zyf1688732 发表于 2023-5-4 16:17
 楼主| 2016976438 发表于 2023-5-4 16:40
debug_cat 发表于 2023-5-4 15:38
学习进度跟不上了

我也学几个月才把这些零零散散的资料整合一起的。学的知识转换不了money才是最痛苦的
debug_cat 发表于 2023-5-4 17:11
2016976438 发表于 2023-5-4 16:40
我也学几个月才把这些零零散散的资料整合一起的。学的知识转换不了money才是最痛苦的

厚积薄发,先掌握技术,沉淀,机会来了自然就有了
Daneellee 发表于 2023-5-4 17:48
感谢楼主谢谢!
lordship 发表于 2023-5-4 19:08
谢谢分享
debug_cat 发表于 2023-12-11 16:54
再次看文章,终于能跟得上了
您需要登录后才可以回帖 登录 | 注册[Register]

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

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

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

GMT+8, 2024-5-3 07:08

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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