中国目前对于PSP的破解在很大程序上就像是一个嗷嗷待哺的婴儿,想来总觉得凄凉.
设想如果M33小组,Davee,Dark Alex团队,还有那个15岁的英国小黑客不来做这个破解事情的话,不来做HEN系统软件.那我们中国人该怎么?
要知道PSP70%的销售在中国,同志是在中国!
我们一直高亢得不能再高亢的爱情热情,我们的民族情操,我们的满腔热忱不能不说在PSP上显得"狐假虎威"
某虽不才,便愿意用这一点突破往来的浮躁"情怀",真的爱国一把.同时我也期待更多的人仁志士能加入其中.
用我们的crack技术来爱一次国
现在网上关于PSP的"破解"文章好像总是不能如意,大家发挥一下网络天赋,看看能不能找到关于PSP1000到3000过程中的上一些破解文章,新闻性的就不要了,电玩巴士里的文章我都看过了.希望还可以有更多的底层文章
=====================我附上一份===========================
TIFF(TagImageFileformat)是Mac中广泛使用的图像格式,它由Aldus和微软联合开发,最初是出于跨平台存储扫描图像的需要而设计的。它的特点是图像格式复杂、存贮信息多。正因为它存储的图像细微层次的信息非常多,图像的质量也得以提高,故而非常有利于原稿的复制。该格式有压缩和非压缩二种形式,其中压缩可采用LZW无损压缩方案存储。不过,由于TIFF格式结构较为复杂,兼容性较差,因此有时你的软件可能不能正确识别TIFF文件(现在绝大部分软件都已解决了这个问题)。目前在Mac和PC机上移植TIFF文件也十分便捷,因而TIFF现在也是微机上使用最广泛的图像文件格式之一。
要分析这个漏洞,一定要能够重现这个漏洞,然后通过跟踪和调试来分析它。m大神发布的漏洞我分析了一下,有两种利用方式,,一个是直接在目录下就溢出,也就是说当你用psp打开了畸形tiff文件所在的目录时,漏洞就已经使寄存器溢出了;另一个是可以用来做自制程序,也就是说,当你打开了畸形tiff文件,那个就会在你本地发生寄存器栈溢出,从而执行任意代码,即shellocde。
理解了如何利用,现在我们的关键就是需要掌握一些tiff图像文件格式规范,不需要很专业的掌握,只要对这种文件格式的基础知识有所了解就足够我们分析漏洞了。下面我来描述一下文件的基本规范,考虑到看英文比较难受的朋友,我特意翻译了一把,希望对大家有所帮助。需要英文原文的朋友也可以从本文的光盘相关中得到。
一个完整的tiff文件首先有8字节的头部(header),头部中含有一个指针指向一个图像文件目录,简称IFD(image file directory),每个IFD包含了重要的图像信息,这些信息是一条一条的存储在IFD中的,称为目录条目,简称DE(directory entry)。具体的说,可以用下面这个图示来说明他们之间的逻辑关系。
首部Header
字节0-1:字节序
“II”(4949.H)——小印第安,低字节存储在内存的低地址
“MM”(4D4D.H)——大印第安,低字节存储在内存的高地址
字节2-3:TIFF文件标识
最好选用42(十进制),同时要看前面的字节序,如果是小印第安,这里就写2A00.H;否则写002A.H
字节4-7:第一个图像文件目录(IFD)在文件中的偏移量(offset)
图像文件目录(IFD)
每一个图像文件目录(IFD)中首先有两个字节表示目录条目(DE)的个数,接着的连续的每12个字节是一个目录条目,每个IFD最后4个字节表示的是下一个IFD的偏移量,如果没有后继IFD的话用一个4字节数字0来结尾。
目录条目(DE)
每一个12字节的DE拥有同样的结构:
字节0-1:本域的标记(Tag)
字节2-3:本域类型(Type)
字节4-7:值的个数
字节8-11:具体的值,或者是一串多个值存储于文件的偏移量
其中类型有多种,最常见的有一下几种:
1=BYTE 8位无符号整数
2=ASCII 8位,其中前7位表示一个ASCII码;最后一位必须是NUL(二进制的0)
3=SHORT 16位无符号整数
4=LONG 32位无符号整数
5=RATIONAL 两个LONG,第一个表示分子;第二个表示分母
有了以上的基本文件格式规范知识后,我们就可以开始研究上面perl代码生成的ms07-055.tif文件了。首先我们来看看文件头部的8个字节,如下:
00000000h: 49 49 2A 00 90 3E 00 00 80 3F E0 50 38 24 16 0D ; II*.?..€?郟8$..
根据上面的知识很容易知道其中的含义,49 49表示小印第安字节序;2A 00是TIFF文件文件标识;90 3E 00 00表示该文件的第一个IFD在文件的00003E90偏移量处。
那么我们下一步很自然的去00003E90偏移量处去解析第一个IFD,可见该文件中只有这样一个IFD。
00003e90h: 0F 00 FE 00 04 00 01 00 00 00 00 00 00 00 00 01 ; ..?............
00003ea0h: 03 00 01 00 00 00 80 02 00 00 01 01 03 00 01 00 ; ......€.........
00003eb0h: 00 00 00 02 00 00 02 01 03 00 FF 00 00 00 DA 3B ; .............?
00003ec0h: 00 00 03 01 03 00 01 00 00 00 05 00 00 00 06 01 ; ................
00003ed0h: 03 00 01 00 00 00 02 00 00 00 11 01 04 00 56 00 ; ..............V.
00003ee0h: 00 00 38 3D 00 00 15 01 03 00 01 00 00 00 03 00 ; ..8=............
00003ef0h: 00 00 16 01 04 00 01 00 00 00 06 00 00 00 17 01 ; ................
00003f00h: 04 00 56 00 00 00 E0 3B 00 00 1A 01 05 00 01 00 ; ..V...?........
00003f10h: 00 00 CA 3B 00 00 1B 01 05 00 01 00 00 00 D2 3B ; ..?..........?
00003f20h: 00 00 1C 01 03 00 01 00 00 00 01 00 00 00 28 01 ; ..............(.
00003f30h: 03 00 01 00 00 00 02 00 00 00 3D 01 03 00 01 00 ; ..........=.....
00003f40h: 00 00 01 00 00 00 0 0 00 00 00 ; ..........
其中大头的0F 00表示这个IFD中有15个DE,每个DE含有12个字节,我在上面把他们隔开了。为了让大家对这个15个DE有更清楚的了解,我把他们按照含义列成一个表,如下所示:
序号 标记Tag 类型Type 值个数Count 值获偏移量Value/Offset
0 00FE 0004 0000 0001 0000 0000
1 0100 0003 0000 0001 0000 0280
2 0101 0003 0000 0001 0000 0200
3 0102 0003 0000 00FF 0000 3BDA
4 0103 0003 0000 0001 0000 0005
5 0106 0003 0000 0001 0000 0002
6 0111 0004 0000 0056 0000 3D38
7 0115 0003 0000 0001 0000 0003
8 0116 0004 0000 0001 0000 0006
9 0117 0004 0000 0056 0000 3BE0
10 011A 0005 0000 0001 0000 3BCA
11 011B 0005 0000 0001 0000 3BD2
12 011C 0003 0000 0001 0000 0001
13 0128 0003 0000 0001 0000 0002
14 013D 0003 0000 0001 0000 0001
在这15个DE中,最值得关注的是第4个,也就是上面用黑底绿字标出的一行,这个DE告诉我们,它的数值个数有0000 00FF个,也就是255个;数值类型均是SHORT(0003),16位,占两个字节;这255个数值在文件中的偏移量是0000 3BDA。以我的直觉来看,我认为这255个数值就是最后造成栈溢出的直接凶手,可能就是在程序中处理这255个数值时,经这个数值读入某函数的局部变量(可能是个数组)时,由于开辟的数组元素数有限,而且没有比较255这个数和开辟的数组元素个数的大小关系,就开始读入,最终导致了缓冲区溢出的发生。——这也只是我的合理预测和猜想,到底是不是如我所说,需要跟踪调试才能证明。下面我们就用OllyDBG来调试一把。
由于程序控制的EIP最终为0c0c0c0c,如果不修改一下的话,跟踪调试的时候,调试器是不会停下来的,那么很简单,直接把0c0c0c0c改为FFFFFFFF即可,这样调试器会发现程序在执行非法内存地址的指令,就会停下来。停下来后,你可以去检查栈中的蛛丝马迹。根据函数调用的原理,我们可以知道覆盖EIP为FFFFFFFF前执行的指令应该是RET指令,在这个指令执行前一定有一个函数被调用,而这个函数也很有可能就是最终发生溢出的函数,那么在ESP指向的栈空间的上部一定有一些返回地址,那么我们可以把几个可以的返回地址记下来,然后在下一次程序加载了这个地址所属的dll文件或exe文件时拦截,并把断点下到刚才记录下来的地址紧邻的前一条指令处,那么一旦断下来,有两种境况,第一种情况是,栈还未被覆盖,说明溢出还没有发生,那么只要单步跟踪仔细调试,就可以跟到发生溢出的那行代码;第二种境况是,栈已经被覆盖了,那说明记录下来的几个可疑地址是不正确的,根本就没有在这些函数内部发生溢出,这就需要在刚才发生了溢出后的栈中继续前溯,一定会在溢出之前断下程序,因为无论如何程序在溢出之前一定调用过某个程序。而这个程序的返回地址会保存在栈中。
我用这种办法,首先发现了两个可疑地址:内存中的690B 3F71和690B 3163,最后发现断到690B 3163时还尚未发生溢出,那么我就F7跟进去,最终通过单步调试的方法,终于找到了溢出发生的函数。原来是在read()函数中溢出的。
为什么会在这个read()函数中溢出呢?我们首先来看看read()函数的定义:
_read()读文件函数
原形:int _read(handle,buffer,count)
int handle;//文件句柄
void *buffer;//存放读出数据的缓冲区
unsigned count;//一次读出的字节数
功能:从由handle指定的文件中读取由count指定字节数的数据到buffer
返回值:0-0xfffe(实际读出的字节数);-1(错误)
再来看看给read()函数传入的三个参数是什么,其中handle是一个句柄,就是前面那个畸形文件的句柄;buf是一个内存地址,指向了栈空间的一个内存单元;len=1FE=FF×2。结合前面的分析,连起来就是说,这里调用read()函数的目的是要把前面那255个2字节数值全部复制到内部某个变量中。而且在调用read()函数之前并没有做任何长度上的检查,因此这是一定能导致溢出的,因为内部变量的空间是有限的,而文件中存储的数值个数却是不确定的。我想到此,本漏洞导致的根本原因已经找到了,就是未检查文件DE指定的数值个数和长度就开始往内部变量中写入,最终覆盖了previous EBP和返回地址,导致发生栈溢出。
回顾本漏洞的重现过程和分析过程,我们首先学习了TIFF文件格式的一些基本规范,由于利用程序中没有详细的注释为什么那样构造畸形文件,因此我们需要掌握一定的文件格式规范。接着我们结合利用程序对其生成的畸形tiff文件,根据格式规范来分析,发现在第一个IFD中的第4个DE有一定的可疑,该DE指定了数值类型为16位的无符号整数,一共指定了连续的FF个这样的数值。最终通过跟踪调试的方法,定位到了栈溢出发生的函数——read()函数,这是微软下的c标准运行库中的一个函数,功能是从由handle指定的文件中读取由count指定字节数的数据到buffer。而在对tiff文件做处理的文件中调用read()函数时,传入的buffer竟然是内部变量,而且从文件中读取并写入这个内部变量前没有做任何的检查操作。这就是导致漏洞发生的根本原因。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课