Re练习之ASM汇编逆向

debu8ger Lv3

基本介绍

以一个耳熟能详的Hello World程序切入:

#include <stdio.h>
int main(int argc, char* argv []) {
printf("Hello, world!\n");
return 0;
}

通过gcc编译为ASM形式并输出得到:

    .section .rodata
.LC0:
.string "Hello, world!"
.text
.globl main
.type main, @function
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], edi //字符串值赋给edi
mov QWORD PTR [rbp-16], rsi
mov edi, OFFSET FLAT:.LC0 //传参完毕
call puts //调用printf函数,输出字符串
mov eax, 0 //eax赋值为0,作为函数返回值
leave
ret

过程很简单,

首先的.LC0定义了前面的Hello World!字符串,告诉编译器该字符串的地址

下面的则是main函数的汇编块:

  1. 第8-12行为初始化堆栈,开辟适合的内存区域,而rbp、rsp、edi则是寄存器,负责储存数据
  2. 13行后都是执行函数。

常见的汇编指令:mov、sub、call、ret等。

  1. mov:赋值。格式为mov 被赋值方 要赋的值
  2. sub:递减。
  3. call:调用。
  4. ret&leave:出栈。代表一个函数的结束。(通常在wasmleave不常见)

常见指令

1.loop循环指令:

mov rax,0
mov rcx,236
s:
add rax,123
loop s
leave
ret

以上执行的便是对123累加236次。在上述代码中,rcx寄存器保存循环次数loop指令每执行一次,rcx -1。

2.无条件跳转指令:

lable:
mov edx,0

jmp lable

上述的jmp即为无条件跳转。

3.条件跳转指令:

lable:
mov edx,1

cmp ebx,0
je lable

上述代码将ebx的值与0对比:为真,跳转至lable,所以je为条件跳转关键词。

一般的条件跳转指令与cmp、test指令混在一起用:

lable:
mov edx,1

test ebx,0
jnz lable //代表标志位为0则跳转

常见的条件跳转指令:

  • je:等于(Jump if Equal )
  • jne:不等于(Jump if Not Equal)
  • jz:零标志位为1(Jump if Zero)
  • jnz:零标志位为0(Jump if Not Zero)
  • js:符号标志位为1(Jump if Sign)
  • jns:符号标志位为0(Jump if Not Sign)
  • jpjpe:奇偶标志位为1
  • jnpjpo:奇偶标志位为0
  • jo:溢出标志位为1
  • jno:溢出标志位为0
  • jgjnle:大于
  • jgejnl:大于/等于
  • JLJNGE:小于
  • JLEJNG:小于/等于

常见的位运算指令:

  • AND:与运算。AND AX, BX,即AXBX进行逻辑与运算,保存结果至AX
  • OR:或运算。OR AX, BX,即AXBX进行逻辑或运算,保存结果至AX
  • XOR:异或运算。XOR AX, BX,即异或运算,保存结果至AX
  • NOT:取反操作。NOT CX,将CX取反,保存结果至CX

4.函数传参:

通常函数の返回值保存在ax寄存器(eax、rax)

参数一般按顺序保存在cx、dx、si

在64位汇编当中,则按照rcx、rdx、r8、r9、r10、r11 ...顺序储存

5.lea地址加载:

格式为lea rdx, [my_var],将my_var地址赋值给rdx寄存器。

6.xchg数值交换:

格式为xchg ax, bx,将axbx的数值交换

例题

一.[HDCTF 2023]easy_asm

IDA打开附件,只有一个start函数,空格切换至汇编代码:

re_lian1

re_lian2

很容易看到,待解密的flag就是seg001的内容,

圈出来的便是xor加密逻辑:al存储seg001的值,cl存储异或的key "0x10"

要想解密,就得异或回去,seg001 ^0x10 = decrypt_flag

最终的exp:

enc_flag = [
0x4E, 0x6F, 0x74, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x21, 0x24,
0x45, 0x71, 0x75, 0x61, 0x6C, 0x21, 0x24, 0x58, 0x54, 0x53, 0x44,
0x56, 0x6B, 0x5A, 0x65, 0x63, 0x64, 0x4F, 0x71, 0x4F, 0x75, 0x23,
0x63, 0x69, 0x4F, 0x71, 0x43, 0x7D, 0x6D, 0x24
]

decrypt_flag = ''.join([chr(b ^ 0x10) for b in enc_flag])
print(decrypt_flag)

#flag: HDCTF{Just_a_e3sy_aSm}

暂时只做了这一道asm逆向的,之后有做到会接着补充,嗯~ o( ̄▽ ̄)o

Comments
On this page
Re练习之ASM汇编逆向