能力值:
( LV9,RANK:530 )
2 楼
只加说明, 不重传附件: 1. 溢出是在下面的CODE中: 004002EE |. F3:A5 rep movs dword ptr es:[edi], dword ptr [esi]
// ESI = VirtualAlloc() 返回的动态地址, 设为XXXXXXXX
当 ECX >= 0x0D 时, 上面的操作会使返回地址被覆盖,
004002F0 |> \5F pop edi
004002F1 |. 33C0 xor eax, eax
004002F3 |. 5E pop esi
004002F4 |. C9 leave
004002F5 \. C3 retn // 正常返回0x00400383 2. DWORD 个数(ECX) 由下面计算得到:
ECX = (0x1A-EAX) * EAX - 0x9C
只有当EAX=0x0D时, ECX将等于0x0D, 满足条件.
而当EAX为其它值时, ECX要么太小; 要么太大, 会使 rep movs 越界; 或者是负数. 都不满足条件 3. 问题变为, 文件的前两个DWORD, 设为D1, D2. 要满足下面的条件
64 bit 无符号运算:
( ((D2<<0x20)|D1) * 0x4847464569948F1B % 0x5BE6FF82A5164785 ) & 0xFFFFFFFF == 0x0000000D // (等式1)
设
T2:T1 = (D2:D1) * 0x4847464569948F1B // (a)
U2:U1 = (T2:T1) % 0x5BE6FF82A5164785 // (b)
其中T2, D2, U2 为高32bit, T1, D1, U1为低32bit, 则U1=0x0000000D
由 (b) 可得
T1 = 0x0000000D, T2: from 0x00000000 to 0x5BE6FF82 (d)
T1 = 0x0000001A, T2: from 0x5BE6FF82 to 0xB7CDFF04 (e)
T1 = 0x00000027, T2: from 0xB7CDFF04 to 0xFFFFFFFF (f)
由 (a) 可得
T1 = D1 * 0x69948F1B (g)
由 (d),(e),(f) 和(g) , 把 D1 from 0x0000000 to 0xffffffff 验证一遍.
只有三个值 满足条件: 0x8AD397F7, .. ,..
其中只有第一个值0x8AD397F7最好(自己验证, 在此略过), 按下面的变化
004002CC |> /8031 1C /xor byte ptr [ecx], 1C
004002CF |. |8A11 |mov dl, byte ptr [ecx]
004002D1 |. |3051 01 |xor byte ptr [ecx+1], dl
004002D4 |. |41 |inc ecx
004002D5 |. |41 |inc ecx
004002D6 |. |4F |dec edi
004002D7 |.^\75 F3 \jnz short 004002CC 0x8AD397F7 ==> EB, 7C, CF, 45
EB, 7C ==> jmp short $+0x80
这时候 D2==0x00000001 就能使等式1 成立. 4. 所以问题就成在 004002F5 时能返回ESI中的地址XXXXXXXX就好了.
XXXXXXXX 在栈中, 与正常返回地址的关系如下:
[ESP+...]:
00400383
XXXXXXXX
如果将返回地址覆盖成0x004002F5, 将使得
004002F5 \. C3 retn
被执行, 这样一来, 就会到xxxxxxxx处去运行 5. 下面就是写CODE, call MessageBox,
然后返回0x00400397继续执行, 只要ESP, EBP 恢复正确就行.
能力值:
(RANK:570 )
3 楼
验证通过~~
能力值:
(RANK:570 )
4 楼
93.41892132858407478067564790265