Hexagon学习
Hexagon 学习
Hexagon 是高通(Qualcomm)开发的 数字信号处理器(DSP) 架构,专为移动设备、物联网和边缘计算设计,以高效能、低功耗为核心优势。它被集成在高通骁龙(Snapdragon)系列芯片中
- hexagon用allocframe开辟栈帧:LR压栈,FP压栈,SP减去一定数值向低地址开辟,FP设置成指向旧FP的指针。deallocframe/dealloc_return用于销毁栈帧/销毁栈帧并返回,从栈底取回FP和LR。

- 一共有32个32位通用寄存器,r0-r31。存在寄存器对,可以当做64位寄存器使用,如r0和r1可以合并成r1:0
- r29-r31是别名寄存器。r29是SP,r30是FP,r31是LR寄存器。SP是栈顶寄存器,FP是栈(底)寄存器,LR是储存返回地址的寄存器。
看汇编感觉是类arm架构
主要的汇编有
plaintext
1 | allocframe(#0x10) #开辟栈空间 |
例题
『2025VNCTF』hexagon
cpp
1 | .text:00020460 .global vuln |
发现allocframe只开辟了0x10个字节的栈空间,然后read的起始地址是从fp-8开始的,再结合32位的4字节地址,显然有栈溢出8个字节,溢出到FP和LR的存储空间,而LR是存取返回地址的,便有劫持返回地址。
解法1-system执行
看了官方wp之后
从libc.so中找到system,发现偏底层的system实现方式是通过posix_spawn进程创建函数(理解为fork+execve即可),通过对参数的简单分析,可以知道r1=”/bin/sh”,然后argv[] = {“sh”, “-c”, user_input, NULL};,而这个usr_input是通过fp-0x10输入的,详情自行查看posix_spawn的参数
然后回到题目发现一开始有一个scanf函数是输入fp-0x10的,那么局势就很明朗了,同时由于qemu的libc是不会改变的,因此传入一个/bin/sh的地址就行啦
libc地址的寻找:
这里是通过日志来寻找的
cpp
1 | set_tid_address(1073672412,1073672412,-4,0,1072439316,67108864) = 7 |
而这个1073672412是指针地址,通常由libc分配的存储tid(线程id)的,从libc中寻找到对应的结构体
cpp
1 | .bss:0012F0DC __thread_list_lock:.space 1 // DATA XREF: __init_tp+70↑o |
相减获得libc_base=0x3FEC0000(算是取巧吧,因为我的qemu单步执行坏掉啦/(ㄒoㄒ)/~~)
本地环境与远程有差距,不过方法类似
cpp
1 | p = process(['qemu-hexagon' , '-d', 'in_asm,exec,cpu,nochain', '-strace', '-dfilter', '0x20420+0xc0', '-D', './log', './main']) |
解法2-栈迁移
对1血脚本学习。
python
1 | stack_addr = 0x4080f1c8 |
有意思的
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 S1nec-1o's B1og!