断断续续写了几个月的Hash工具,当时学习Win32汇编和熟悉算法的实践,想来自己一直一个人单干,也不知写得怎么样,如有错漏,请海涵指出,不胜感激。
源文件夹结构
Common里面就是放包含的文件以及各个段
Verify里面是Md5和SHA1,每组计算用的算法
Hash.asm是基本的消息流程
_MessageDeal.asm是一堆子程序,其实是Hash.asm使用的
_Thread.asm这个是负责计算的工作者线程,这个最苦逼了,修修改改改了不下10遍还是不满意,没有想到好的编写结构,不过怎么复杂,有一部分是为了兼容大文件的,继而使用内存映射文件,所以又要分段映射,除此此外,为了显示进度条,还要由这个子程序通知主窗口更新进度条……所以越写越长。
manifest.txt这个应该算是一个特殊的资源文件,加入以后就可以使用Visual Styles,而非很丑的经典风格,附上使用说明http://msdn.microsoft.com/zh-cn/library/windows/desktop/bb773175(v=vs.85).aspx 要在汇编中使用,特别注意要先用invoke InitCommonControls,否则程序会自动退出
_CmdLine.asm这个是老罗写好的命令行解析,我直接拿来用了,所以本工具也是支持命令行的,另外为了实现添加右键菜单,也用到了带参数运行。
数据结构
INHASH STRUCT
lpFiledir dd ? ;文件名指针
bList dd ? ;计算哪些值,这里偷懒,每8位标志一个哈希值是否计算
lpObject dd ? ;事件句柄,用来停止
hWnd dd ? ;接收消息的窗口句柄
INHASH ENDS
OUTHASH STRUCT
lpFiledir dd ? ;文件名指针
stSize FILELEN<> ;文件大小
MD5 dd 4 dup(?) ;MD5值
SHA1 dd 5 dup(?) ;SHA1值
OUTHASH ENDS
INHASH是传递给计算线程的信息,OUTHASH 是计算线程返回的信息
部分源码
先是计算64Byte/分组的MD5
_FF proc ta,tb,tc,td,M,ts,k
mov eax,tb ;F(tb,tc,td)
mov ecx,eax
and eax,tc
not ecx
and ecx,td
or eax,ecx
add eax,ta
add eax,M
add eax,k
mov ecx,ts
rol eax,cl
add eax,tb
ret
_FF endp
_GG proc ta,tb,tc,td,M,ts,k
mov eax,td ;G(tb,tc,td)
mov ecx,eax
and eax,tb
not ecx
and ecx,tc
or eax,ecx
add eax,ta
add eax,M
add eax,k
mov ecx,ts
rol eax,cl
add eax,tb
ret
_GG endp
_HH proc ta,tb,tc,td,M,ts,k
mov eax,tb ;H(tb,tc,td)
xor eax,tc
xor eax,td
add eax,ta
add eax,M
add eax,k
mov ecx,ts
rol eax,cl
add eax,tb
ret
_HH endp
_II proc ta,tb,tc,td,M,ts,k
mov eax,td ;I(tb,tc,td)
not eax
or eax,tb
xor eax,tc
add eax,ta
add eax,M
add eax,k
mov ecx,ts
rol eax,cl
add eax,tb
ret
_II endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;_MD5to64 ebx,edx固定分配作state_md5和带变换的字符lpMemory
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_MD5to64 proc uses eax ebx ecx edx lpMemory,lpstate_md5
local @aa,@bb,@cc,@dd
mov ebx,lpstate_md5
mov edx,lpMemory
push dword ptr [ebx]
pop @aa
push dword ptr [ebx+4]
pop @bb
push dword ptr [ebx+8]
pop @cc
push dword ptr [ebx+12]
pop @dd
invoke _FF,@aa,@bb,@cc,@dd,[edx+0],7,0d76aa478h;第1轮
mov @aa,eax
invoke _FF,@dd,@aa,@bb,@cc,[edx+4],12,0e8c7b756h;第2轮
mov @dd,eax
invoke _FF,@cc,@dd,@aa,@bb,[edx+8],17,0242070dbh;第3轮
mov @cc,eax
invoke _FF,@bb,@cc,@dd,@aa,[edx+12],22,0c1bdceeeh;第4轮
mov @bb,eax
invoke _FF,@aa,@bb,@cc,@dd,[edx+16],7,0f57c0fafh;第5轮
mov @aa,eax
invoke _FF,@dd,@aa,@bb,@cc,[edx+20],12,04787c62ah;第6轮
mov @dd,eax
invoke _FF,@cc,@dd,@aa,@bb,[edx+24],17,0a8304613h;第7轮
mov @cc,eax
invoke _FF,@bb,@cc,@dd,@aa,[edx+28],22,0fd469501h;第8轮
mov @bb,eax
invoke _FF,@aa,@bb,@cc,@dd,[edx+32],7,0698098d8h;第9轮
mov @aa,eax
invoke _FF,@dd,@aa,@bb,@cc,[edx+36],12,08b44f7afh;第10轮
mov @dd,eax
invoke _FF,@cc,@dd,@aa,@bb,[edx+40],17,0ffff5bb1h;第11轮
mov @cc,eax
invoke _FF,@bb,@cc,@dd,@aa,[edx+44],22,0895cd7beh;第12轮
mov @bb,eax
invoke _FF,@aa,@bb,@cc,@dd,[edx+48],7,06b901122h;第13轮
mov @aa,eax
invoke _FF,@dd,@aa,@bb,@cc,[edx+52],12,0fd987193h;第14轮
mov @dd,eax
invoke _FF,@cc,@dd,@aa,@bb,[edx+56],17,0a679438eh;第15轮
mov @cc,eax
invoke _FF,@bb,@cc,@dd,@aa,[edx+60],22,049b40821h;第16轮
mov @bb,eax
invoke _GG,@aa,@bb,@cc,@dd,[edx+4],5,0f61e2562h;第17轮
mov @aa,eax
invoke _GG,@dd,@aa,@bb,@cc,[edx+24],9,0c040b340h;第18轮
mov @dd,eax
invoke _GG,@cc,@dd,@aa,@bb,[edx+44],14,0265e5a51h;第19轮
mov @cc,eax
invoke _GG,@bb,@cc,@dd,@aa,[edx+0],20,0e9b6c7aah;第20轮
mov @bb,eax
invoke _GG,@aa,@bb,@cc,@dd,[edx+20],5,0d62f105dh;第21轮
mov @aa,eax
invoke _GG,@dd,@aa,@bb,@cc,[edx+40],9,002441453h;第22轮
mov @dd,eax
invoke _GG,@cc,@dd,@aa,@bb,[edx+60],14,0d8a1e681h;第23轮
mov @cc,eax
invoke _GG,@bb,@cc,@dd,@aa,[edx+16],20,0e7d3fbc8h;第24轮
mov @bb,eax
invoke _GG,@aa,@bb,@cc,@dd,[edx+36],5,021e1cde6h;第25轮
mov @aa,eax
invoke _GG,@dd,@aa,@bb,@cc,[edx+56],9,0c33707d6h;第26轮
mov @dd,eax
invoke _GG,@cc,@dd,@aa,@bb,[edx+12],14,0f4d50d87h;第27轮
mov @cc,eax
invoke _GG,@bb,@cc,@dd,@aa,[edx+32],20,0455a14edh;第28轮
mov @bb,eax
invoke _GG,@aa,@bb,@cc,@dd,[edx+52],5,0a9e3e905h;第29轮
mov @aa,eax
invoke _GG,@dd,@aa,@bb,@cc,[edx+8],9,0fcefa3f8h;第30轮
mov @dd,eax
invoke _GG,@cc,@dd,@aa,@bb,[edx+28],14,0676f02d9h;第31轮
mov @cc,eax
invoke _GG,@bb,@cc,@dd,@aa,[edx+48],20,08d2a4c8ah;第32轮
mov @bb,eax
invoke _HH,@aa,@bb,@cc,@dd,[edx+20],4,0fffa3942h;第33轮
mov @aa,eax
invoke _HH,@dd,@aa,@bb,@cc,[edx+32],11,08771f681h;第34轮
mov @dd,eax
invoke _HH,@cc,@dd,@aa,@bb,[edx+44],16,06d9d6122h;第35轮
mov @cc,eax
invoke _HH,@bb,@cc,@dd,@aa,[edx+56],23,0fde5380ch;第36轮
mov @bb,eax
invoke _HH,@aa,@bb,@cc,@dd,[edx+4],4,0a4beea44h;第37轮
mov @aa,eax
invoke _HH,@dd,@aa,@bb,@cc,[edx+16],11,04bdecfa9h;第38轮
mov @dd,eax
invoke _HH,@cc,@dd,@aa,@bb,[edx+28],16,0f6bb4b60h;第39轮
mov @cc,eax
invoke _HH,@bb,@cc,@dd,@aa,[edx+40],23,0bebfbc70h;第40轮
mov @bb,eax
invoke _HH,@aa,@bb,@cc,@dd,[edx+52],4,0289b7ec6h;第41轮
mov @aa,eax
invoke _HH,@dd,@aa,@bb,@cc,[edx+0],11,0eaa127fah;第42轮
mov @dd,eax
invoke _HH,@cc,@dd,@aa,@bb,[edx+12],16,0d4ef3085h;第43轮
mov @cc,eax
invoke _HH,@bb,@cc,@dd,@aa,[edx+24],23,004881d05h;第44轮
mov @bb,eax
invoke _HH,@aa,@bb,@cc,@dd,[edx+36],4,0d9d4d039h;第45轮
mov @aa,eax
invoke _HH,@dd,@aa,@bb,@cc,[edx+48],11,0e6db99e5h;第46轮
mov @dd,eax
invoke _HH,@cc,@dd,@aa,@bb,[edx+60],16,01fa27cf8h;第47轮
mov @cc,eax
invoke _HH,@bb,@cc,@dd,@aa,[edx+8],23,0c4ac5665h;第48轮
mov @bb,eax
invoke _II,@aa,@bb,@cc,@dd,[edx+0],6,0f4292244h;第49轮
mov @aa,eax
invoke _II,@dd,@aa,@bb,@cc,[edx+28],10,0432aff97h;第50轮
mov @dd,eax
invoke _II,@cc,@dd,@aa,@bb,[edx+56],15,0ab9423a7h;第51轮
mov @cc,eax
invoke _II,@bb,@cc,@dd,@aa,[edx+20],21,0fc93a039h;第52轮
mov @bb,eax
invoke _II,@aa,@bb,@cc,@dd,[edx+48],6,0655b59c3h;第53轮
mov @aa,eax
invoke _II,@dd,@aa,@bb,@cc,[edx+12],10,08f0ccc92h;第54轮
mov @dd,eax
invoke _II,@cc,@dd,@aa,@bb,[edx+40],15,0ffeff47dh;第55轮
mov @cc,eax
invoke _II,@bb,@cc,@dd,@aa,[edx+4],21,085845dd1h;第56轮
mov @bb,eax
invoke _II,@aa,@bb,@cc,@dd,[edx+32],6,06fa87e4fh;第57轮
mov @aa,eax
invoke _II,@dd,@aa,@bb,@cc,[edx+60],10,0fe2ce6e0h;第58轮
mov @dd,eax
invoke _II,@cc,@dd,@aa,@bb,[edx+24],15,0a3014314h;第59轮
mov @cc,eax
invoke _II,@bb,@cc,@dd,@aa,[edx+52],21,04e0811a1h;第60轮
mov @bb,eax
invoke _II,@aa,@bb,@cc,@dd,[edx+16],6,0f7537e82h;第61轮
mov @aa,eax
invoke _II,@dd,@aa,@bb,@cc,[edx+44],10,0bd3af235h;第62轮
mov @dd,eax
invoke _II,@cc,@dd,@aa,@bb,[edx+8],15,02ad7d2bbh;第63轮
mov @cc,eax
invoke _II,@bb,@cc,@dd,@aa,[edx+36],21,0eb86d391h;第64轮
mov @bb,eax
mov eax,@aa
add dword ptr [ebx],eax
mov eax,@bb
add dword ptr [ebx+4],eax
mov eax,@cc
add dword ptr [ebx+8],eax
mov eax,@dd
add dword ptr [ebx+12],eax
ret
_MD5to64 endp
再是计算64Byte/分组的SHA1
_SHA1to80 proc uses eax ebx ecx edx lpMemory,lpstate_sha1
local @aa,@bb,@cc,@dd,@ee
local _Sha1Buffer[80]
; Extend the sixteen 32-bit words into eighty 32-bit words:
lea eax,_Sha1Buffer
xor ecx,ecx
mov edx,lpMemory
.while ecx<=15
mov bl,[edx+ecx*4+3]
mov [eax+ecx*4],bl
mov bl,[edx+ecx*4+2]
mov [eax+ecx*4+1],bl
mov bl,[edx+ecx*4+1]
mov [eax+ecx*4+2],bl
mov bl,[edx+ecx*4]
mov [eax+ecx*4+3],bl
inc ecx
.endw
.while ecx<=79
mov ebx,[eax+ecx*4-16*4]
xor ebx,[eax+ecx*4-14*4]
xor ebx,[eax+ecx*4-8*4]
xor ebx,[eax+ecx*4-3*4]
rol ebx,1
mov [eax+ecx*4],ebx
inc ecx
.endw
; Initialize hash value for this chunk:
mov ebx,lpstate_sha1
push dword ptr [ebx]
pop @aa
push dword ptr [ebx+4]
pop @bb
push dword ptr [ebx+8]
pop @cc
push dword ptr [ebx+12]
pop @dd
push dword ptr [ebx+16]
pop @ee
; Main loop:
xor ecx,ecx
.while ecx<=79
.if ecx<=19
mov ebx,@bb
and ebx,@cc
mov edx,@bb
not edx
and edx,@dd
or ebx,edx
add ebx,5A827999h
.elseif ecx>= 40 && ecx <= 59
mov ebx,@bb
and ebx,@cc
mov edx,@bb
and edx,@dd
or ebx,edx
mov edx,@cc
and edx,@dd
or ebx,edx
add ebx,8F1BBCDCh
.else
mov ebx,@bb
xor ebx,@cc
xor ebx,@dd
.if ecx<=39
add ebx,6ED9EBA1h
.else
add ebx,0CA62C1D6h
.endif
.endif
mov edx,@aa ;edx表示temp,ebx表示f+k
rol edx,5
add edx,ebx
add edx,@ee
lea eax,_Sha1Buffer
add edx,[eax+ecx*4]
push @dd
pop @ee
push @cc
pop @dd
mov ebx,@bb
rol ebx,30
mov @cc,ebx
push @aa
pop @bb
mov @aa,edx
inc ecx
.endw
mov ebx,lpstate_sha1
mov edx,@aa
add dword ptr [ebx],edx
mov edx,@bb
add dword ptr [ebx+4],edx
mov edx,@cc
add dword ptr [ebx+8],edx
mov edx,@dd
add dword ptr [ebx+12],edx
mov edx,@ee
add dword ptr [ebx+16],edx
ret
_SHA1to80 endp
_ThreadCalc proc uses eax ebx ecx edx esi lpHashCtrl
assume esi:ptr INHASH
mov esi,lpHashCtrl
;打开文件
invoke CreateFile,addr szFiledir,GENERIC_READ, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax== INVALID_HANDLE_VALUE
invoke SendMessage,[esi].hWnd,WM_HASH,1,0
ret
.endif
mov @hFile,eax
invoke GetFileSize,@hFile,addr @stHashResult.stSize.h
mov @stHashResult.stSize.l,eax
invoke CreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL
mov @hFileMap,eax
push [esi].bList
pop @List
;初始化
invoke RtlMoveMemory,addr @stHashResult.MD5,offset Init_data,16
invoke RtlMoveMemory,addr @stHashResult.SHA1,offset Init_data,20
;计算分段映射的次数
mov edx,@stHashResult.stSize.h
mov eax,@stHashResult.stSize.l
mov ebx,FILEMAPSIZE
div ebx
mov @nPart,eax
mov @nPart_Remainder,edx
inc eax ;进一,进度条刚好完全
shl eax,16 ;低位为最小值,高位为最大值
invoke SendMessage,[esi].hWnd,WM_HASH,2,eax
mov @counth,0
mov @countl,0
mov esi,lpHashCtrl
mov edi,[esi].lpObject ;检测标志,以便停止
mov ebx,FILEMAPSIZE ;
.while @nPart
invoke MapViewOfFile,@hFileMap,FILE_MAP_READ,@counth,@countl,FILEMAPSIZE
mov @lpMemory,eax
invoke _@BlockDispatch,FILEMAPSIZE,@lpMemory,addr @stHashResult,@List
invoke UnmapViewOfFile,@lpMemory
invoke SendMessage,[esi].hWnd,WM_HASH,3,0
mov eax,[edi] ;在耗时最多的地方检验标志
.if !eax
invoke SendMessage,[esi].hWnd,WM_HASH,0,0
jmp break
.endif
add @countl,ebx
adc @counth,0
dec @nPart
.endw
.if @nPart_Remainder
invoke MapViewOfFile,@hFileMap,FILE_MAP_READ,@counth,@countl,@nPart_Remainder
mov @lpMemory,eax
.if @nPart_Remainder>=64 ;将本次映射的前n*64字节计算
invoke _@BlockDispatch,@nPart_Remainder,@lpMemory,addr @stHashResult,@List
.endif
mov eax,@lpMemory ;eax为映射的初始地址
add eax,@nPart_Remainder ; eax为映射最后地址
and @nPart_Remainder,3Fh ;@nPart_Remainder 现在代表%64的余数
sub eax,@nPart_Remainder ; eax为映射最后地址-上面的余数
invoke RtlMoveMemory,addr @buffer_last,eax,@nPart_Remainder ;将剩余不足64字节的数据存入buffer_last
invoke UnmapViewOfFile,@lpMemory
invoke SendMessage,[esi].hWnd,WM_HASH,3,0
.endif
.if @nPart_Remainder>=56
lea ebx,@buffer_last
add ebx,@nPart_Remainder
mov ecx,64
sub ecx,@nPart_Remainder ;ecx=64-@nPart_Remainder
invoke RtlMoveMemory,ebx,offset added,ecx
invoke _@BlockDispatch,64,addr @buffer_last,addr @stHashResult,@List ;先
mov ebx,offset added
add ebx,64
sub ebx,@nPart_Remainder
invoke RtlMoveMemory,addr @buffer_last,ebx,56
.else ;<56则只会变换一轮
lea ebx,@buffer_last
add ebx,@nPart_Remainder
mov ecx,56
sub ecx,@nPart_Remainder
invoke RtlMoveMemory,ebx,offset added,ecx
.endif
;将@countl @counth 组成的64位长度乘以8,变成以bit计算的文件长度
push @stHashResult.stSize.l
pop @countl
push @stHashResult.stSize.h
pop @counth
mov eax,0E0000000h ;将64位数乘以8
and eax,@countl
shr eax,29
shl @countl ,3
shl @counth,3
add @counth,eax
lea ebx,@buffer_last ;填充输入信息长度,并进行最后一次变换
;md5的按照小端排序
push @countl
pop dword ptr [ebx+56]
push @counth
pop dword ptr [ebx+60]
invoke _MD5to64,ebx,addr @stHashResult.MD5
;sha1的按照大端端排序
invoke _ChangeEndian,@counth
mov [ebx+56],eax
invoke _ChangeEndian,@countl
mov [ebx+60],eax
invoke _SHA1to80,ebx,addr @stHashResult.SHA1
;通知窗口完成计算
invoke GlobalAlloc,GMEM_FIXED,sizeof OUTHASH
mov @lpResult,eax
invoke RtlMoveMemory,@lpResult,addr @stHashResult,sizeof OUTHASH ;将
invoke SendMessage,[esi].hWnd,WM_HASH,0,@lpResult
break:
invoke CloseHandle,@hFileMap
invoke CloseHandle,@hFile
assume esi:nothing
ret
_ThreadCalc endp
每次映射的大小由FILEMAPSIZE equ 100000h 决定,我定为1MB
流程是每次映射1MB(当然要是64KB的倍数),最后的一次不足1MB,但又可能大于64KB,那么先将本次映射的前n个64字节计算掉,将剩下的不足64字节放入缓冲区,剩下的看过MD5和SHA1应该都知道怎么做了。
考虑到停止和进度条功能,又在每次映射1MB这部分加了一些语句,
因为这部分是最耗时间的。
后来在实现加入右键的功能时,发现要管理员权限,搜了一圈发现进程无法运行到一半提升权限,想了个方法,以管理员身份带参数运行自身,这个新的实例只是添删右键就退出了,参数?Y和?N代表添加和删除右键。
[课程]Linux pwn 探索篇!