学习大会

dev*_*ium 99 assembly

我决定学习汇编语言.这样做的主要原因是能够理解反汇编的代码,并且可能能够编写更有效的代码部分(例如,通过c ++),做一些代码洞穴等等.我看到有大量不同的程序集所以,就我提到的目的而言,我该如何开始?我应该学习什么样的装配?我想通过首先做一些简单的程序(即计算器)来学习,但目标本身将是与它一起被认可,所以我可以理解所显示的代码,例如IDA Pro.

我正在使用Windows(如果这有任何区别).

编辑:所以,似乎每个人都指向MASM.虽然我明白它具有高级功能,但对于汇编代码程序员来说都很有用,这不是我想要的.它似乎有流行的反汇编程序(如IDA)中没有显示的if,invoke等指令.所以,如果可能的话,我想听到的是任何使用ASM的人的意见(我在IDA中阅读反汇编的exe代码),而不仅仅是"通用"汇编程序员.

编辑:好的.我已经在学习集会了.我正在学习MASM,而不是使用对我来说无关紧要的高级东西.我现在正在做的是在c ++中使用__asm指令尝试我的代码,所以我可以比使用MASM从头开始做所有事情更快地尝试.

old*_*mer 43

我做了很多次,并继续这样做.在这种情况下,你的主要目标是阅读而不是编写汇编程序,我觉得这适用.

编写自己的反汇编程序.不是为了制作下一个最伟大的反汇编器,这个是严格适合你的.目标是学习指令集.无论我是在新平台上学习汇编程序,还是为我曾经知道的平台记住汇编程序.从只需几行代码开始,例如添加寄存器,并在反汇编二进制输出和在输入端添加越来越复杂的指令之间进行乒乓:

1)学习特定处理器的指令集

2)了解如何为所述处理器编写汇编代码的细微差别,以便您可以在每条指令中摆动每个操作码位

3)你使用该指令集的大多数工程师都能更好地学习指令集

在你的情况下有一些问题,我通常建议开始使用ARM指令集,今天发布的ARM产品比其他任何产品都要多(包括x86计算机).但是你现在使用ARM并且不知道足够的汇编程序来编写启动代码或其他熟悉ARM的例程的可能性可能会或可能不会帮助你尝试做什么.ARM首先的第二个也是更重要的原因是因为指令长度是固定大小并且是对齐的.像x86一样拆卸变长指令可能是一个噩梦,作为你的第一个项目,这里的目标是学习不创建研究项目的指令集.第三个ARM是一个完善的指令集,寄存器创建相同,没有个别的特殊细微差别.

所以你必须弄清楚你想要从哪个处理器开始.我建议首先使用msp430或ARM,然后是ARM第一或第二,然后是x86的混乱.无论在什么平台上,任何值得使用的平台都有数据表或程序员参考手册,供参考手册免费提供,包括指令集以及操作码的编码(机器语言的位和字节).为了学习编译器的功能以及如何编写编译器不必费力的代码,了解一些指令集并了解如何在每个指令集上实现相同的高级代码,每个编译器都进行优化设置.你不想进入优化你的代码只是为了发现你已经使它对一个编译器/平台更好,但对其他每个更糟糕.

哦,对于反汇编可变长度指令集,而不是简单地从开始处开始,并像通过ARM一样线性地通过内存分解每四个字节字或像msp430那样每两个字节(msp430有可变长度指令,但你仍然可以通过如果从中断向量表的入口点开始,则线性通过内存.对于可变长度,您希望根据向量表或有关处理器如何引导的信息以及执行顺序中的代码来查找入口点.如果指令不是无条件分支,则必须完全解码每条指令以了解使用了多少字节,假设该指令之后的下一个字节是另一条指令.您还必须存储所有可能的分支地址,并假设它们是更多指令的起始字节地址.有一次我成功了,我通过二进制文件进行了几次传递.从入口点开始,我将该字节标记为指令的开始,然后通过内存线性解码,直到达到无条件分支.所有分支目标都被标记为指令的起始地址.我在二进制文件中进行了多次传递,直到找不到新的分支目标.如果您在任何时候发现说3字节指令但由于某种原因您已将第二个字节标记为指令的开头,那么您就会遇到问题.如果代码是由高级编译器生成的,那么除非编译器正在做一些邪恶的事情,如果代码有手写汇编程序(比如说一个旧的街机游戏),那么很可能会有条件分支永远不会发生比如r0 = 0,如果不是零,则跳转.您可能需要手动编辑二进制文件中的内容才能继续.对于我认为将在x86上的直接目标我不认为你会遇到问题.

我建议使用gcc工具,如果x86是你的目标,mingw32是在Windows上使用gcc工具的简单方法.如果不是mingw32 plus msys是一个很好的平台,用于从binutils和gcc源生成交叉编译器(通常非常简单).mingw32比cygwin有一些优势,比如显着更快的程序,你避免了cygwin dll地狱.gcc和binutils允许你用C或汇编语言编写并反汇编你的代码,你可以阅读更多的网页,告诉你如何做三个中的任何一个或全部.如果您要使用可变长度指令集执行此操作,我强烈建议您使用包含反汇编程序的工具集.例如,x86的第三方反汇编程序将成为一个挑战,因为你从来没有真正知道它是否已经正确拆解.其中一些也依赖于操作系统,目标是将模块编译为二进制格式,其中包含来自数据的信息标记指令,因此反汇编程序可以执行更准确的工作.您对此主要目标的另一个选择是拥有一个可以直接编译到汇编程序以供检查的工具,然后希望当它编译为二进制格式时,它会创建相同的指令.

你的问题的简短(好的稍短)回答.编写反汇编程序以学习指令集.我会从一些RISCy开始,像ARM一样容易学习.一旦你知道一个指令集,其他指令变得更容易,通常在几个小时内,通过第三个指令集你几乎可以立即开始编写代码,使用语法的数据表/参考手册.所有值得使用的处理器都有一个数据表或参考手册,描述了操作码的位和字节之下的指令.学习像ARM这样的RISC处理器和像x86这样的CISC,足以让人感觉到差异,例如必须通过寄存器查看所有内容,或者能够直接在内存上执行少量寄存器或不使用寄存器的操作.三个操作数指令与两个等等.在调整高级代码时,编译多个处理器并比较输出.您将学到的最重要的事情是,无论编写高级代码有多好,编译器的质量和所做的优化选择都会对实际指令产生巨大影响.我推荐llvm和gcc(使用binutils),既不会产生很好的代码,但它们是多平台和多目标,并且都有优化器.两者都是免费的,您可以轻松地从各种目标处理器的源代码构建交叉编译器.

  • "编写自己的反汇编程序" - 我同意,这是我学习它的最佳方式.(怎么了"但我甚至不知道如何编写反汇编程序"?)大声笑. (8认同)

Noo*_*ilk 40

MASM32开始,然后从那里看FASM.但是你会玩MASM很开心.

  • 你不懂集会.你需要了解它.操作码是一个数字.调试器将尝试将操作码解析为其指令(有时很难).您需要了解基本说明.学习MASM将帮助您实现这一目标.不再需要说了. (7认同)
  • 您不必使用所有MASM功能,因为它们就在那里; 如果你认为你会以这种方式学到更多东西,那么你可以把事情看作是你想要的. (5认同)
  • MASM,它的怪癖,错误和所谓的高级功能,使得汇编程序员 - 初学者和专家 - 更加困惑 - 比我能想到的更多. (3认同)

kqu*_*inn 33

从高级别查看时,您手动编写的程序集和编译器生成的程序集通常会有很大差异.当然,程序的内部结构非常相似(a = b + c毕竟只有很多不同的编码方式),但是当你试图对某些东西进行逆向工程时,它们并不是麻烦.编译器将为简单的可执行文件添加大量的样板代码:上次我比较,GCC编译的"Hello World"大约是4kB,而如果在汇编中手动编写则大约是100字节.在Windows上情况更糟:上次我比较(诚然,这是上个世纪)最小的"Hello World"我可以让我的Windows编译器然后选择生成52kB!通常这个样板文件只执行一次,如果有的话,所以它对程序速度影响不大 - 就像我上面所说的那样,程序的核心,大部分执行时间花费的部分,无论是编译还是编译,通常都非常相似用手写的.

在一天结束时,这意味着专家装配程序员和专家汇编程序是两个不同的专业.通常他们是在同一个人身上找到的,但他们真的是分开的,学习如何成为优秀的汇编编码器对于学习逆向工程并不会有太大帮助.

你想要做的就是从英特尔AMD那里获得IA-32和AMD64(两者都包含在一起)架构手册,并查看有关指令和操作码的早期部分.也许在集成语言上阅读一两个教程,只是为了获得汇编语言的基础知识.然后获取一个您感兴趣的样本程序并将其反汇编:逐步完成其控制流程并尝试了解它正在做什么.看看你是否可以修补它以做其他事情.然后再尝试另一个程序,并重复直到你足够舒服,试图实现更有用的目标.您可能对逆向工程社区制作的"裂缝"等内容感兴趣,这对于对逆向工程感兴趣的人来说是一个挑战,并希望在此过程中学到一些东西.它们的难度范围从基本(从这里开始!)到不可能.

最重要的是,你只需要练习.与许多其他学科一样,通过逆向工程,练习可以完美......或者至少更好.

  • 我担心的是,虽然理论上我可以阅读论文并掌握它们的意思,直到我开始写自己的东西,我不相信我会真正理解它.你说我可以从改变代码的一小部分开始,但为了做到这一点,我首先必须知道IDA pro使用什么样的组装"风味". (3认同)

Ale*_*lli 15

我将反对大多数答案并推荐Knuth的MIPS RISC架构的MMIX变体.它不会像x86或ARM汇编语言那样实用有用(并不是说它们在大多数现实生活中都非常重要...... ;-),但它会为你解锁Knuth最新的魔力关于算法和数据结构的深层次低级理解的最伟大的杰作版本 - TAOCP,"计算机程序设计的艺术".我引用的两个网址中的链接是开始探索这种可能性的好方法!


Nic*_*kis 12

(我不了解你,但我很高兴装配)

您的电脑中已经安装了一个用于试验装配的简单工具.

转到"开始"菜单 - >"运行",然后键入debug

debug(命令)

debug是DOS,MS-DOS,OS/2和Microsoft Windows(仅x86版本,而不是x64)中的命令,它运行程序debug.exe(或旧版DOS中的DEBUG.COM).Debug可以充当汇编程序,反汇编程序或十六进制转储程序,允许用户以交互方式检查内存内容(使用汇编语言,十六进制或ASCII),进行更改,并有选择地执行COM,EXE和其他文件类型.它还有几个子命令,用于访问特定的磁盘扇区,I/O端口和内存地址.MS-DOS调试以 16位进程级别运行,因此仅限于16位计算机程序.FreeDOS Debug还有一个支持32位DPMI程序的"DEBUGX"版本.

教程:


如果您想了解在IDA Pro(或OllyDbg)中看到的代码,您需要了解编译代码的结构.我推荐Reversing:Reverse Engineering的秘密

debug当我开始学习装配(15年前)时,我进行了几周的实验.
请注意,debug在基本机器级别工作,没有高级程序集命令.

现在一个简单的例子:

a开始编写汇编代码 - 键入下面的程序 - 最后给g它运行它.

替代文字


(如果寄存器设置为- INT 21在屏幕上显示存储在DL寄存器中的ASCII字符- 终止程序)AH2INT 20

  • @ericp,你不必点击ctrl-c.例如,键入"a"和[enter]开始编写汇编代码.如果按两次[enter],则退出组装模式.`g`和[enter]运行它(默认偏移100). (2认同)

mbl*_*ll8 8

我发现黑客:剥削的艺术是一个有趣和有用的方式进入这个主题...不能说我曾经直接使用过这些知识,但这并不是我阅读它的原因.它使您更加丰富地了解代码编译的指令,这有时对于理解更微妙的错误很有用.

不要被标题推迟.本书的第一部分大部分内容都是Eric Raymond的"Hacking"一词:创造性的,令人惊讶的,几乎是偷偷摸摸的解决棘手问题的方法.我(也许你)对安全方面的兴趣不大.


Jos*_*man 7

我不会专注于尝试在汇编中编写程序,至少在开始时是这样.如果你使用的是x86(我假设你是,因为你正在使用Windows),有很多奇怪的特殊情况,这是毫无意义的.例如,许多指令假设您正在对未明确命名的寄存器进行操作,而其他指令适用于某些寄存器但不适用于其他寄存器.

我会充分了解您理解基础知识的预期架构,然后直接跳进去尝试理解编译器的输出.用英特尔手册武装自己,然后直接进入编译器的输出.将感兴趣的代码隔离成一个小函数,这样您就可以确保理解整个事物.

我会考虑基础知识:

  • 寄存器:有多少个,它们的名字是什么,它们的大小是多少?
  • 操作数顺序:add eax, ebx表示"将ebx添加到eax并将结果存储在eax中".
  • FPU:了解浮点堆栈的基础知识以及如何转换为fp或从fp转换.
  • 寻址模式:[base + offset*multiplier],但乘数只能是1,2或4(或者可能是8?)
  • 调用约定:参数如何传递给函数?

在很多时候,编译器发出的内容会令人惊讶.让它成为一个难题,弄清楚为什么编译器认为这将是一个好主意.它会教你很多.

它可能也有助于用Agner Fog的手册武装自己,特别是列出一个的说明.它将大致告诉您每条指令的成本,尽管在现代处理器上更难直接量化.但它有助于解释为什么,例如,编译器为避免发出idiv指令而走得太远.

我唯一的另一条建议是,当你有一个选择时,总是使用英特尔语法而不是AT&T.在这一点上,我曾经非常中立,直到有一天我意识到两者之间的某些指令完全不同(例如,movslqAT&T语法是movsxdIntel语法).由于手册都是使用英特尔语法编写的,因此请坚持使用.

祝好运!