2025-11-21-AT&T
学习 AT&T 为了 pwn
由于 objdump 反汇编的二进制程序使用 AT&T语法,我必须好好学习
此汇编语法有如下特点
- 操作数顺序:源 在前 目的 在后
mov %rsp, %sbp表示把rsp的值移动到rbp
- 寄存器以 % 为前缀, 立即数以
$前缀 - 函数调用时,参数通过寄存器传递:
- rdi 第一个
- rsi 第二个
- rdx 第三个
- 常见指令:
- 栈操作:
push、pop - 数据移动:
mov - 函数调用:
call - 返回:
ret
- 栈操作:
概念:
- 函数序言:在函数开始时执行,用于设置堆栈帧(stack frame)。通常包括保存旧的基指针(%rbp)、设置新的基指针(指向当前堆栈顶部),以及可选的堆栈空间分配。这确保了函数在执行期间有独立的局部变量空间和调用上下文。
- 函数尾声:在函数结束时执行,用于清理堆栈帧并返回调用者。通常包括恢复旧的基指针、释放堆栈空间(如果有分配),并执行返回指令。
例题:warmup_csaw_2016
1 | 40060d: 55 push %rbp |
这个代码是一个独立的函数
有标准的 prologue 和 epilogue
- 函数序言:
push %rbp将旧的基指针压入堆栈,保存调用函数的堆栈帧基地址。mov %rsp,%rbp将堆栈指针的值移动到基指针 堆栈用于保存上下文
- 尾声:
pop %rbp从堆栈中弹出之前保存的旧基指针值,恢复%rbp 到调用函数的状态ret从函数返回,将控制权交还给调用者, 并可能清理堆栈
代码:
pusb %rbp旧基地址入栈mov %rsp,%rbp堆指针数值>基指针mov $0x400734,%edi将立即数 0x400734 移动到edi寄存器,x86-64中,edi用于传递函数的第一个参数,这里准备调用system函数。0x400734很可能是一个字符串的地址。 二进制中,字符串常存放在制度数据段(.rodata) 可推特 0x400734只指向一个系统命令call 4004d0 <system@plt>通过 过程链接表 (PLT) 调用system函数,system函数会执行edi中的字符串作为系统命令pop %rbp从栈中弹出旧基地址,恢复rbp的值ret从函数返回,控制流回到调用者
1 | 40061d: 55 push %rbp |
push %rbp , move %rsp, %rbp建立新栈帧add $0xffffffffffffff80, %rsp- 0x0xffffffffffffff80 在补码表示中是 -128,等价于
sub $0x80, %rsp可能用于局部变量或缓冲区 mov $0xa, $edx将edx设置为10 edx 通常用于第三个参数或长度值move $0x400741, $esi:将esi 设置为0x400741可能是另一个字符串地址
- 0x0xffffffffffffff80 在补码表示中是 -128,等价于
1 | 400651: ba 0d 06 40 00 mov $0x40060d,%edx |
mov $0x40060d,%edx将 edx设置为 0x40060dmov $0x400751,%esi将esi设置为 0x400751 AI说可能是一个格式化字符串地址 例如%s,%pmov %rax,%rdi把 rdi的值设置成rax的值,这里可能指向一个缓冲区(例如 栈上的空间) rdi是 sprintf的第一个参数mov %0x0,%eax把eax清零了- 在x86-64中,这常用于可变参数函数(如
sprintf),表示没有浮点参数
- 在x86-64中,这常用于可变参数函数(如
call 400510 <sprintf@plt>通过过程链接表调用 sprintf函数,参数是- rdi :目标缓冲区 地址来自rax
- rsi :格式化字符串 0x400751
- rdx:可变参数 也就是 0x40060d
所以,这行代码可能将地址0x40060d格式化为字符串并存储到缓冲区
如果格式字符串是"%p",它会将地址转换为字符串表示。
lea -0x80(%rbp), %rax加载有效地址,计算rbp - 0x80到 rax- 这确认了缓冲区在栈上的位置
mov $0x9, %edx把edx设置为9mov %rax, %rsi将 rax移动到 rsi , rsi是write的第二个参数(数据缓冲区)mov $0x1, %rsi将 edi设置为1,这是文件描述符 (1表示标准输出stdout)call 4004c0 <write@plt>调用 write函数 向stdout输出9字节的数据从缓冲区mov $0x1, %edx把edx设置成1 可能用于后续操作
总结这部分:代码使用sprintf将函数地址0x40060d格式化为字符串,存储到栈缓冲区,然后通过write输出前9字节到屏幕。这可能是为了泄漏地址(在CTF中常见),帮助攻击者计算偏移或绕过ASLR。
不仅是pwn 想打好二进制安全 汇编肯定要学的多多的,而且要多学几种,例如 nasm,还有2024 中科大比赛的时候出现的uxntal ,这个指令集我就不会。
所以你们到底怎么学的啊怎么什么都会!