首页
社区
课程
招聘
[注意]《The Shellcoder's Handbook》中的笔误
2007-2-22 23:53 9002

[注意]《The Shellcoder's Handbook》中的笔误

2007-2-22 23:53
9002
[arhat注:大家可能会对给这样的帖子设置精华有疑惑,但我想只要对别人有帮助的都在允许范围之内。更何况kmyc指出了很多概念上的错误。]

第三章 Shellcode

第30页10行:在正常情况下,每个系统调用支持6个参数,分别保存在EBX,ECX,EDX,ESI,EDI和EPB里。
英文原文是:Each syscall can have a maximum of six arguments, which are inserted into EBX, ECX, EDX, ESI, EDI, and EPB, respectively.

我查阅了80x86体系结构手册中关于寄存器的内容,所有80x86系列的寄存器里似乎并没有一个叫EPB的,所以在这里猜测,可能是把EBP误写成EPB了。我没有查阅关于Linux系统调用的fastcall参数传递的具体信息,所以这里不能妄下定论。不过MSDN中关于Windows的fastcall的具体信息倒是有案可查:The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. The following list shows the implementation of this calling convention.
Argument-passing order : The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.

以前没怎么在论坛上发过贴,也不懂论坛上的规矩,本来准备回复在汇总和勘误的那个主题上的,可是那个主题已经回复了5页多了,怕我这篇帖子发上去没人看得到,所以只好新发一个主题了。如果占了版面,敬请管理员删贴,谢谢。

arhat大哥翻译得辛苦,菜鸟在此表示深深的敬意。看到前面勘误的帖子,似乎问题都集中在前三章,我也是刚看完前三章。不知是后面的章节真的没有疏漏,还是有别的原因。arhat大哥翻译的文章是菜鸟们学习的宝贵资源,希望arhat大哥能再多翻译些这样的文献,提携提携我们这样的菜鸟。最后希望arhat大哥的《The Shellcoder's Handbook》的翻译早日完成,最后出版成书。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

收藏
点赞7
打赏
分享
最新回复 (12)
雪    币: 2108
活跃值: (208)
能力值: (RANK:1260 )
在线值:
发帖
回帖
粉丝
arhat 31 2007-2-23 12:06
2
0
感谢!
我把它更新到勘误帖。

原文是EPB,应该是印刷错误,感谢您的细心。
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
kmyc 4 2007-2-24 16:20
3
0
今天读完了第四章

第四章 格式化串漏洞

第50页第5段(这个结果虽然出乎我们的意料,……)
第2行:……,我们刚刚输入的字符串中的4个字符被当作“数字”传递给printf函数,……
英文原文是:……,so 4-byte segments from the string are being passed as the "numbers" to be substituted into the string.
按照我的理解,原文的意思应该是:我们刚刚输入的字符串每4个字符被当作1个“数字”传递给printf函数
也就是说,字符串被分成每4个字符一段,分别作为格式化参数传递给了printf函数。而译文给人的感觉是:我们刚刚输入的字符串中“只有”4个字符被当作“数字”传递给printf函数,给人产生了误解和歧义。

第58页16行:
得到

200-index BBA41424242

原文是:
We get:

200-index BBBA41424242
少打了一个B(从41424242可以看出来,而且原文没有少)。看来arhat大哥连代码都是手工敲进去的,真辛苦了。

第62页第2段(注意标为粗体的那行。)
那里比较有意思,在错误的调用vsnprintf之后,程序的作者正确的调用了printf。
原文是:The interesting point is that there's a call to printf right after the vulnerable call to vsnprintf.

注意:vulnerable的意思是:易受攻击的, 易受...的攻击。在C语法上,程序的作者对vsnprintf调用符合规则,并不构成错误,但是在vsnprintf的具体实现上,使得程序的作者对vsnprintf的那种调用方式“易受攻击”。而与之相对应的,对printf的调用应该是“合适”的(不易受(格式化串漏洞)攻击)。译文中使用“错误”和“正确”似乎有些不恰当。在计算机对指令的执行过程中,正确和错误都是相对的,在计算机硬件看来,它“存储程序,顺序执行”,并没有犯错。所以我们说软件“漏洞”,而一般不说软件“错误”。

第70页第10行
……;然后利用%n把你写入栈上参数的数据写入地址。

原文是:Then, use %n to write to the address using the parameter you wrote to the stack.

我认为,文章实际的意思说,本打算向某个地址写入数据,可是因为这个地址四个字节中某个字节为0,所以不能以$'(地址(little-endian形式))%(数据-6-4)x%(本字符串第一个字的位置(如果从该位置读取一个字,那么内容将是我们前面以little-endian形式存储的地址))$n'的形式提交字符串,否则会在刚开始四个字节的地址处被截断。所以需要先将地址写到一个参数的位置,即提交"%(地址-6-4)x%(存储该参数地址的位置(也许需要另一个参数,可以用开始的方法把“该参数”的地址存到这个参数里,前提是:“该参数”的地址没有NULL,汗))$n",然后提交"%(数据-6-4)x%(该参数的位置)$n"……汗……

根据这些想法,我以为,这句翻译成:“然后利用%n把你写入栈上参数的数据作为地址进行写入。”也许可以消除歧义和误解。

同样根据上面的想法,在下一句中,将原文的"Alternatively"翻译成“换句话说”似乎有些牵强,因为后面一句话说的情况相比前面分析的情况比较特殊,两者并不对等。前面的情况适用比较普遍,而后面的情况,即NULL出现在地址的最高字节,可以把地址放在提交的字符串的末尾因为地址以little-endian形式存储,所以最高字节的NULL刚好作为字符串的结尾被提交,而一般情况(前面的情况)都是把地址放在字符串的首部。这种做法只是为了方便地址寻找,相比把地址放在别的地方而把放地址的那个地址再存起来,这种情况会简单很多。但是这要求地址只有最高字节为空。所以,"Alternatively"翻译“作为另一种选择(相对比较特殊的情况)”比较好。

第71页倒数第6行
这个方法也可以使用哪些在处理格式化串之后,……
将“那”打成“哪”了,一般用拼音输入法比较容易犯这样的小错误,看来大哥的翻译工作真是废寝忘食,太辛苦了呀。

最后谈点小意见,这章的最后一句是:that they are worth understanding.
愚以为,对基本原理的理解,应该胜过简单的掌握和熟练现成的技巧。理解了原理,加上我们充满灵感的想象力,就可以搞出无数令人称奇的新技巧。软件每时每刻都在更新,不可能有一劳永逸的现成的技巧,所以,“理解(原理,规律)”,活的理解(ing),可能比“学”“习”(现成的技巧)更重要。
雪    币: 2108
活跃值: (208)
能力值: (RANK:1260 )
在线值:
发帖
回帖
粉丝
arhat 31 2007-2-24 18:09
4
0
花了近一个小时,把这些地方过了一遍,已经更新到勘误里了。
再次感谢kmyc的认真。
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
kmyc 4 2007-2-25 00:45
5
0
自我感觉堆溢出比栈溢出和格式化字符串漏洞繁琐一些。
读到了5.2.1基本堆溢出的后半部分,把期间发现的问题写出,供arhat大哥参考

第5章 堆溢出

第72页第1段第1行
译文:本章主要介绍Linux上的堆溢出,使用的堆实现源自Doug Lee最初的malloc实现,……
原文:This chapter focuses on heap overflows on the Linux platform, which uses a malloc implementation originally written by Doug Lee,……
注:不好意思,第一行就找您的岔。原文中的which应该指代的是“堆溢出”(heap overflows),“使用的堆实现”似乎有些不合适,因为堆的实现在这里暂时还看不出和主题什么关系。也许改为:……,利用了源自Doug Lee最初的malloc实现,…… 较妥。不知arhat大哥意下如何。

第72页第2段第4行
译文:一个典型的Linux程序通常包括.bss段(为初始化的全局变量),用brk()或mmap()分配的、由malloc()使用的.data段(已初始化的全局变量)。
原文:Typically a Linux program has a .bss (global variables that are uninitialized) and a .data segment (global variables that are initialized) along with other segments used by malloc() and allocated with the brk() or mmap() system calls.
注:这个问题就比较严重了,必须要纠正,技术上是不能有这样的概念错误的:.data段当然不是用brk()或mmap()分配的、由malloc()使用的,.data段就只是用来存放已初始化的全局变量的。从原文中也可以看出“along with other segments used by……”。
愚以为,应翻译成:一个典型的Linux程序通常包括.bss段(为初始化的全局变量),.data段(已初始化的全局变量)和其他的用brk()或mmap()等系统调用分配的、由malloc()使用的一些段。总之概念上决不能有混淆,希望arhat大哥在这个基本概念的基础上对这句话做出语言上更准确地翻译。

第77页第1行
译文:……,并把buf2块头部的0xfffffff0改为0xffffffff。
原文:…… and changing the chunk header of buf2 to have a size of 0xfffffff0 and a previous size of 0xffffffff.
注:原文的意思是:修改buf2块的头部,使得buf2块的大小变成0xfffffff0,buf2块的前一块的大小变成0xffffffff。其实就是把buf2块头部的8个字节分别修改成0xffffffff,0xfffffff0。因为buf2块头部的8个字节分别存储的是buf2块的前一块的大小(32位)和buf2块的大小(32位)。从下面的这条命令本身也可以看出:
(gdb) run `python -c 'print
"A"*1024+"\xff\xff\xff\xff"+"\xf0\xff\xff\xff"'`

第77页第5段第3行
译文:那你应该注意,在大多数情况下,free()是infree的封装;……
原文:…… you should note that free() is really a wrapper to intfree in most cases.
注:笔误,将intfree写成了infree,少了一个n。

第78页第1,2段
译文:
  在第一条指令(mov 0x8(%esi), %edx)里,……

  在第二条指令(add %eax, %edi)里,……
原文:
  In the first instruction (mov 0x8(%esi), %edx), ……

  In the second instruction (add %eax, %edi), ……
注:arhat大哥的翻译和原文内容一致,可惜原文内容写错了。稍微阅读下这两段,就会发现,这两条指令本应该是这两段上面的那两条指令,可惜被误写为这两段下面的那五条指令的前两条,完全对不上号。
故,原文应为:
  In the first instruction (mov 0xfffffff8(%edx),%eax), ……

  In the second instruction (sub %eax,%esi), ……

译文也应相应作出修改。

第78页第4段第1行
译文:……,接着用前一个块的大小减去4改写buf2的块头部;……
原文:……, then overwrite the chunk header of buf2 with a previous size of -4. ……
注:arhat大哥理解错作者的意思了,其实作者是说用-4(补码0xfffffffc)填充buf2的块头部的前4个字节,也就是存储前一个块的大小的那32位。从下面的这条命令本身可以看出来:
(gdb) r `python -c 'print
"A"*(1024)+"\xfc\xff\xff\xff"+"\xf0\xff\xff\xff"+"AAAAABCDEFGH" '`
雪    币: 2108
活跃值: (208)
能力值: (RANK:1260 )
在线值:
发帖
回帖
粉丝
arhat 31 2007-2-25 08:07
6
0
今天起的比较早,一上论坛,就发现了,汗。。。
容我看一看,再更新到勘误上。
雪    币: 625
活跃值: (1057)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
xzchina 1 2007-2-25 18:11
7
0
我今天才体会到翻译一本书是那么的辛苦,要付出的太多太多。
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 14 2007-2-25 18:41
8
0
看书也挺辛苦的,看一会头就晕了
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
kmyc 4 2007-2-25 20:30
9
0
第79页最后一行
译文:我们正好可以把word1和栈上的地址作为word2。
原文:We can just use that as word1 and an address on the stack as word2.
注:根据上下文,我推断,作者这里的意思是说把exit函数指针(that所指代的)的地址作为word1(其实实际应该是word1+12),而栈上的某个地址(当然是某个shellcode的首地址啦)作为word2。因为word2会写入word1+12,所以改写了本来指向exit函数的函数指针,使得对exit函数的调用变成了对栈上word2地址处的跳转。不知arhat大哥意下如何。

搞了一天,只能说,算是把第5章后面的部分走马观花了一遍,而且还花了很多时间精力查阅别的描述堆溢出的资料。这部分看得确实很累,我想关键原因在于我对malloc(),free()等函数的内部过程的不了解,实际上,利用堆溢出很大程度建立在对malloc(),free()等函数对堆的数据结构的建立和操作的利用上。堆溢出确实繁琐,不如栈溢出那样自然;另一方面,堆溢出漏洞存在范围之广,种类之多,我想,两者之间也是有联系的。作为一只菜鸟,我自认为有必要把堆溢出这个问题弄得更透彻,包括查阅更多资料,请教高手,再加上自己的思考。

很不好意思,折腾了两天,给arhat大哥的译作找了这么多茬。arhat大哥翻译 《The Shellcoder's Handbook》,甚是辛苦,希望arhat大哥能早日完成这项翻译工作,使菜鸟们受福。前五章内容虽然是在linux上实现,可是明显是理论含量高于技术含量,对操作与开发经验要求不高,所以像我这样稍微具备了一些关于汇编语言和操作系统原理知识的菜鸟,尚且有一些发言权。这本书和arhat大哥的译作我会继续往下看,不过可能除了关于windows方面的内容也许我还有一点发言权外,其他高层的技术含量很高的内容,我也不知我是否能理解其中内涵。这本书是我学习buffer overflow的入门书,而这本书也确实合适,理论含量适当且内容组织严谨而不花哨。当然,我最初的入门文章应该算是α1的《娱乐和牟利目的堆栈溢出》。我会继续努力学习关于buffer overflow方面以及更多类似的内容,在此,也热切希望能加入一个有更多学习伙伴和高手的进取的集体中,我想,看雪学院是这样一个集体。

最后,希望arhat大哥 《The Shellcoder's Handbook》的翻译工作早日完成,最后出版成书,让全国广大的爱好者受益。
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
kmyc 4 2007-2-26 00:26
10
0
把第六章浏览了一遍,发现很多内容(关于DCE-RPC,DCOM)根本就不知道,我真是该好好补补课了,本以为我对windows方面的了解还有一定的广度呢,看来我的眼光太狭窄了,真成井底之蛙了。

第六章 Windows的广阔原野

第90页第3段第1行
译文:……,在1991年首次发行了Windows 3.1。……
原文:……, with its first release in 1991 as Windows NT 3.1 .……
注:Windows 3.1和Windows NT 3.1还是不同的,其实在XP以前,Windows系列和Windows NT一直是Microsoft的两条主线,两者有不同的内核,面向不同的对象。比如Windows 3.1不是一个独立的操作系统,必须在DOS下进行加载,很像现在Linux下的XWindow。而Windows NT 3.1从一开始就立足于全新的内核,是一个独立的操作系统。
Windows NT 3.1到Windows NT 4.x到Windows NT 5.0(Windows 2000)
Windows 3.x到Windows 9x到Windows Me
最后两个系列合并成了Windows XP,后来又有了Windows 2003及现在的Windows Vista
很小的时候就在DOS上接触了Windows 3.1(在命令行下输入win加回车,呵呵),作为Windows发展历史的见证人,关于这个问题我还是有发言权的,呵呵。

第95页第5段第2行
译文:……和Todd Sabin的DCE-RPC(http://razor.bindview.com/)。
原文:…… and Todd Sabin's DCE-RPC tools (available from http://razor.bindview.com/).
注:DCE-RPC当然不是Todd Sabin的啦,arhat大哥这里少翻译了一个“tools”,其实应该是:“Todd Sabin的DCE-RPC工具包”。或者直接就是“Todd Sabin的DCE-RPC tools”。

第100页第4段第1行
译文:……,大部分是由未公开的,……
原文:……, and many of these are undocumented ……
注:根据上下文,我认为译文中多打了一个“由”字,本来应该是:“大部分是未公开的”。而且如果不去掉这个“由”字,则译文有些文法不通。

第100页第4段第2行
译文:例如,加载LibraryA()时(把DLL载入内存),……
原文:For example, Load_LibraryA(), which loads a DLL into memory,……
注:这个API我用过,所以我有发言权,这个函数应该是LoadLibraryA(),在MSDN里面查不到这个函数的,顶多查到LoadLibrary(),其实LoadLibrary()是定义在windows.h里面的一个宏,其实大家也应该想到了,还有另一个函数,就是LoadLibraryW()。LoadLibraryA()和LoadLibraryW()的区别就在于接受dll路径及文件名作为参数时,一个把参数处理成ASC单字符,一个处理成宽字符。这些MSDN里面一点都没有提到。我之所以用到LoadLibraryA()这个函数(一般肯定就用LoadLibrary()了),是因为那时搞远程DLL注入,就是利用CreateRemoteThread()在远程进程内创建线程,线程的功能就是载入DLL,当然线程函数就要用LoadLibrary(),可是LoadLibrary()其实根本就是个宏,根本不可能在kernel32.dll中GetProcAddress(),所以必须用LoadLibraryA()或LoadLibraryW()。
不好意思说多了,其实原文也有误导,偏偏在一个完整的函数中间加一个“_”(注:要是在Windows里面真的调用Load_LibraryA(),是绝对调不成功的,而且Win32API是绝不可能在函数名里面有个“_”的),结果也误导了arhat大哥。其实文章后面很快就讲到了DLL注入类似的内容,而且也正确地书写了LoadLibraryA()(这次arhat大哥当然翻译得就没错啦)。

第101页第6段第1行
译文:WSASicjet(),调用WSASicjet()而不是……
原文:WSASocket() Calling WSASocket() instead of ……
注:明显的笔误,在译文里这个函数怎么看怎么不对劲怎么又似曾相识。WSASocket()这个函数我也用过,当时看来相比socket()的优势就是可以交叠处理提高效率。
雪    币: 2108
活跃值: (208)
能力值: (RANK:1260 )
在线值:
发帖
回帖
粉丝
arhat 31 2007-2-26 09:37
11
0
甚是感谢kmyc,如果翻译这本书的第二版,一定请你来审校!
据说英文第二版今年8月份能出

翻译这本书我是尽力了,但有两点局限:
一是英文基础不好,翻译这本书是凭着一腔热血才坚持下来的
二是某些基础知识没有掌握好,书中涉及的知识面较广,有些我也不会,也是边翻译边学习的,难免会出错

说以上两点,并不是推卸责任,而是提醒读者:一是不要尽信书,翻译可能有不妥的地方,如果遇到不理解的地方,最好查一下原文,然后在网上查一下相关资料;
二是多加实践,我在翻译的过程中,并没有一一加以实验,从而造成理解上的缺失。
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
kmyc 4 2007-2-26 10:30
12
0
arhat大哥真是太谦虚了。其实我也就算是一热心读者,现在我也只是第一次看这本书。我的英文比较差,直接看原著很累,而且看这本书是用作shellcode这方面知识的入门,所以主要看arhat大哥的译作。看到发现不对劲的地方,会拿出原文对照对照。前几章的内容因为我都能理解,所以尚能找找碴,关于后面的技术含量很高的内容,对于我这样的菜鸟就不好说了。比如看堆那一章那些文字的同时我也在翻看关于堆溢出的其他的资料。我现在看这本书是一边看一边学,有的内容看得快一些,有些可能就会很慢。不过arhat大哥说到这本书第二版可能今年8月份出,到那时我的水平可就不会是现在这样了,所以到时说不定可以试一试,呵呵。还有希望arhat大哥不要太在乎翻译中的这些小bug,无错不成书嘛,我们成天用的windows还不是一大堆bug。希望arhat再接再厉,把整本书翻出来,给我们这样的电子书读者一个整体上的概观。再次感谢arhat大哥无私的奉献和热情,相比arhat大哥的工作,我这点工作就根本算不上什么,这好比相对windows设计团队构建windows的庞大工程,一两个玩家花点精力找几个bug又算得了什么呢。
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
kmyc 4 2007-2-28 00:16
13
0
第七章 Windows Shellcode

第105页第6段第2行
译文:我们逐行分析heaoverflow.c,看它到底做了些什么!
原文:Let's take a line-by-line look at the shellcode, heapoverflow.c, and see how it works.
注:这个C文件名是:heapoverflow.c,译文少打了一个p。

看到这里就没有再看下去了。
本来昨天就不断地告诫自己不要再看下去了,应该好好补补课,特别是操作系统的具体运行上。可是今天还是忍不住看了,毕竟这本书是本好书,对我太有诱惑了。可是第7章只看了开头就冷静下来了,技术含量对我来说还是偏高,看着太累,所以也只找了个没任何技术含量的碴。说实话,就算比我硬着头皮看下去,也不可能再像之前几章那样找些有理论含量的碴了,因为知之为知之,不知为不知;看不进去的,一字一句看得再认真,也和看阿拉伯文没有什么区别。我不想打肿脸充胖子,搞一天看一章的大跃进。学习是一个循序渐进的过程,不能揠苗助长,否则必然会适得其反。打好坚实的理论基础,配合对相关知识的了解,才是更上一层楼的捷径,书看得累,看不进去,正说明了我需要补课了,不能再看了,就像肚子不舒服就是身体告诉你不能再吃了一样。
我想之后的时间我会静下心来,耐心地从底层开始补课,不会再像刚开始一样一下子发出一大堆的勘误。也希望大家能对我的学习和研究给些建议,推荐一些好书,我不胜感激。

最后感谢arhat对我的这些皮毛的工作的关注和鼓励,和arhat大哥翻译整本书的工程比起来,我这点工作真是算不了什么。
游客
登录 | 注册 方可回帖
返回