逆向分析 160个CrackMe五星052

发布时间:2024年01月19日

#逆向分析 160个CrackMe 052

闲来无事,工作上有调整,等待来年安排,日常的学习还是不能松懈,好久没搞2进制了,最近正在刷pwn和CrackMe,看到了一个160集合感觉不错,刷了几周了,做了20多个了吧,也不知道哪个好,随便搞了下,感觉这5星级的还是挺有意思的,故分析发文。

工具和环境

环境:win10 x64 chs

工具:x64dbg IDA BinaryNinja

编译器:gcc

大体扫一眼

  • 看图标和UI应该是mfc的。
  • 类型应该是Name/Serail类型的。
  • DIE跑一下:UPX的壳。
  • 简单输入Name和Serial测试下,有弹窗。

脱壳

那些在xp上好有用的工具都不太兼容win10,魔改版的LoadPE + ImportREC 修复的exe时灵时不灵的。

还好x64dbg仅有的一个插件解决了这个问题。

x64dbg + esp定律找到OEP,使用x64dbg自带的Scylla,三下五除二搞定。

?

?

找算法函数

第一种办法就是 IDA根据导入表MessageBox函数,交叉引用找到算法。

第二种就是通过OD或者x64dbg动态调试,弹出对话框后,暂停进程,调用栈回溯,也能找到算法函数。

这里我就不过多赘述。

分析

直接拖入IDA,通过导入表MessageBoxA的交叉引用找到4处引用,2个函数。

第一个函数是MFC封装的MsgBox函数,根据它的交叉引用很快找到了数据处理和比较的地方。

封装的MsgBox

1

2

3

4

5

6

7

8

9

10

11

12

13

14

int __thiscall sub_4100A8(_DWORD *this, LPCSTR lpText, LPCSTR lpCaption, UINT uType)

{

??const CHAR *v4; // eax

??HWND v6; // ecx

??v4 = lpCaption;

??if ( !lpCaption )

????v4 = (const CHAR *)*((_DWORD *)AfxGetModuleState() + 4);

??if ( this )

????v6 = (HWND)this[7];

??else

????v6 = 0;

??return MessageBoxA(v6, lpText, v4, uType);

}

根据MsgBox交叉引用,找到处理函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

UPX0:00401C20 sub???? esp, 608h

UPX0:00401C26 push??? ebx

UPX0:00401C27 push??? ebp

UPX0:00401C28 push??? esi

UPX0:00401C29 mov???? ebp, ecx

UPX0:00401C2B push??? edi

UPX0:00401C2C mov???? ecx, 7Dh ; '}'

UPX0:00401C31 xor???? eax, eax

UPX0:00401C33 lea???? edi, [esp+3Ch]

UPX0:00401C37 rep stosd

UPX0:00401C39 mov???? ecx, 7Dh ; '}'

UPX0:00401C3E lea???? edi, [esp+424h]

UPX0:00401C45 rep stosd

UPX0:00401C47 mov???? ecx, 7Dh ; '}'

UPX0:00401C4C lea???? edi, [esp+230h]

UPX0:00401C53 rep stosd

UPX0:00401C55 lea???? eax, [esp+3Ch]

UPX0:00401C59 push??? 64h ; 'd'

UPX0:00401C5B push??? eax

UPX0:00401C5C lea???? ecx, [ebp+5Ch]

UPX0:00401C5F call??? MfcGetText????????????????????? ;? 获取Name的字符串 name = esp + 3c

UPX0:00401C64 lea???? ecx, [esp+424h]

UPX0:00401C6B push??? 64h ; 'd'

UPX0:00401C6D push??? ecx

UPX0:00401C6E lea???? ecx, [ebp+0ACh]

UPX0:00401C74 call??? MfcGetText????????????????????? ; 获取Code的字符串存在 esp + 0x424

UPX0:00401C79 lea???? edi, [esp+3Ch]

UPX0:00401C7D or????? ecx, 0FFFFFFFFh

UPX0:00401C80 xor???? eax, eax

UPX0:00401C82 lea???? edx, [esp+230h]

UPX0:00401C89 repne scasb

UPX0:00401C8B not???? ecx???????????????????????????? ; 求name长度

UPX0:00401C8D sub???? edi, ecx

UPX0:00401C8F mov???? eax, ecx

UPX0:00401C91 mov???? esi, edi

UPX0:00401C93 mov???? edi, edx

UPX0:00401C95 shr???? ecx, 2

UPX0:00401C98 rep movsd?????????????????????????????? ; name复制到esp+230h

UPX0:00401C9A mov???? ecx, eax

UPX0:00401C9C and???? ecx, 3

UPX0:00401C9F rep movsb

UPX0:00401CA1 lea???? ecx, [esp+230h]

UPX0:00401CA8 push??? ecx

UPX0:00401CA9 call??? __strrev??????????????????????? ; 将name反转

UPX0:00401CAE lea???? edi, [esp+234h]

UPX0:00401CB5 or????? ecx, 0FFFFFFFFh

UPX0:00401CB8 xor???? eax, eax

UPX0:00401CBA add???? esp, 4

UPX0:00401CBD repne scasb

UPX0:00401CBF not???? ecx???????????????????????????? ; 求反转后长度

UPX0:00401CC1 sub???? edi, ecx

UPX0:00401CC3 lea???? edx, [esp+3Ch]

UPX0:00401CC7 mov???? esi, edi

UPX0:00401CC9 mov???? ebx, ecx

UPX0:00401CCB mov???? edi, edx

UPX0:00401CCD or????? ecx, 0FFFFFFFFh

UPX0:00401CD0 repne scasb

UPX0:00401CD2 mov???? ecx, ebx

UPX0:00401CD4 dec???? edi

UPX0:00401CD5 shr???? ecx, 2

UPX0:00401CD8 rep movsd?????????????????????????????? ; strcat(name,strrev(name))

UPX0:00401CDA mov???? ecx, ebx

UPX0:00401CDC lea???? eax, [esp+18h]

UPX0:00401CE0 and???? ecx, 3

UPX0:00401CE3 push??? eax

UPX0:00401CE4 push??? offset aSoftwareMicros????????? ; "SOFTWARE\\Microsoft\\Windows\\CurrentVe"...

UPX0:00401CE9 push??? 80000002h

UPX0:00401CEE rep movsb

UPX0:00401CF0 call??? ds:RegOpenKeyA????????????????? ; 打开注册表

UPX0:00401CF6 mov???? ebx, ds:RegQueryValueExA??????? ; 查询ProductID

UPX0:00401CFC lea???? ecx, [esp+14h]

UPX0:00401D00 lea???? edx, [esp+230h]

UPX0:00401D07 push??? ecx

UPX0:00401D08 mov???? ecx, [esp+1Ch]

UPX0:00401D0C lea???? eax, [esp+14h]

UPX0:00401D10 push??? edx

UPX0:00401D11 push??? eax

UPX0:00401D12 push??? 0

UPX0:00401D14 push??? offset aProductid?????????????? ; "ProductID"

UPX0:00401D19 mov???? dword ptr [esp+24h], 1

UPX0:00401D21 mov???? dword ptr [esp+28h], 100h

UPX0:00401D29 push??? ecx

UPX0:00401D2A call??? ebx ; RegQueryValueExA????????? ; 查询ProductID

UPX0:00401D2C lea???? edi, [esp+230h]

UPX0:00401D33 or????? ecx, 0FFFFFFFFh

UPX0:00401D36 xor???? eax, eax

UPX0:00401D38 lea???? edx, [esp+3Ch]

UPX0:00401D3C repne scasb

UPX0:00401D3E not???? ecx

UPX0:00401D40 sub???? edi, ecx

UPX0:00401D42 mov???? dword ptr [esp+10h], 1

UPX0:00401D4A mov???? esi, edi

UPX0:00401D4C mov???? edi, edx

UPX0:00401D4E mov???? edx, ecx

UPX0:00401D50 or????? ecx, 0FFFFFFFFh

UPX0:00401D53 repne scasb

UPX0:00401D55 mov???? ecx, edx

UPX0:00401D57 dec???? edi

UPX0:00401D58 shr???? ecx, 2

UPX0:00401D5B rep movsd?????????????????????????????? ; 将查询的字符串strcat到name

UPX0:00401D5D mov???? ecx, edx

UPX0:00401D5F lea???? eax, [esp+14h]

UPX0:00401D63 and???? ecx, 3

UPX0:00401D66 push??? eax

UPX0:00401D67 mov???? eax, [esp+1Ch]

UPX0:00401D6B lea???? edx, [esp+14h]

UPX0:00401D6F rep movsb

UPX0:00401D71 lea???? ecx, [esp+234h]

UPX0:00401D78 mov???? dword ptr [esp+18h], 100h

UPX0:00401D80 push??? ecx

UPX0:00401D81 push??? edx

UPX0:00401D82 push??? 0

UPX0:00401D84 push??? offset aRegisteredowne????????? ; "RegisteredOwner"

UPX0:00401D89 push??? eax

UPX0:00401D8A call??? ebx ; RegQueryValueExA????????? ; 查询RegisteredOwner

UPX0:00401D8C lea???? edi, [esp+230h]

UPX0:00401D93 or????? ecx, 0FFFFFFFFh

UPX0:00401D96 xor???? eax, eax

UPX0:00401D98 lea???? edx, [esp+3Ch]

UPX0:00401D9C repne scasb

UPX0:00401D9E not???? ecx???????????????????????????? ; 求注册表查询字符串长度

UPX0:00401DA0 sub???? edi, ecx

UPX0:00401DA2 mov???? esi, edi

UPX0:00401DA4 mov???? ebx, ecx

UPX0:00401DA6 mov???? edi, edx

UPX0:00401DA8 or????? ecx, 0FFFFFFFFh

UPX0:00401DAB repne scasb

UPX0:00401DAD mov???? ecx, ebx

UPX0:00401DAF dec???? edi

UPX0:00401DB0 shr???? ecx, 2

UPX0:00401DB3 rep movsd

UPX0:00401DB5 mov???? ecx, ebx

UPX0:00401DB7 and???? ecx, 3

UPX0:00401DBA rep movsb?????????????????????????????? ; 将查询的字符串strcat到name

UPX0:00401DBC lea???? edi, [esp+3Ch]????????????????? ; 由于win10缺少这几个注册表项,其得到的name= name + strrev(name) +strrev(name) + strrev(name)

UPX0:00401DC0 or????? ecx, 0FFFFFFFFh???????????????? ; 如果xp下应该是 name + strrev(name) + ProducID(查询得到字符串) + RegisterOwner(查询的字符串)

UPX0:00401DC3 repne scasb

UPX0:00401DC5 not???? ecx???????????????????????????? ; 求组合后的长度

UPX0:00401DC7 lea???? eax, [esp+2Ch]

UPX0:00401DCB dec???? ecx

UPX0:00401DCC push??? eax

UPX0:00401DCD mov???? esi, ecx

UPX0:00401DCF call??? Md5InitState??????????????????? ; 初始化md5的4个state

UPX0:00401DD4 lea???? edx, [esp+esi+40h]

UPX0:00401DD8 mov???? ecx, 13h

UPX0:00401DDD xor???? eax, eax

UPX0:00401DDF mov???? edi, edx

UPX0:00401DE1 rep stosd?????????????????????????????? ; 清空name后面19 * 4 字节

UPX0:00401DE3 add???? esp, 4

UPX0:00401DE6 inc???? esi

UPX0:00401DE7 stosw

UPX0:00401DE9 mov???? ecx, esi

UPX0:00401DEB stosb

UPX0:00401DEC and???? ecx, 3Fh??????????????????????? ; 对齐数据64

UPX0:00401DEF mov???? eax, 40h ; '@'????????????????? ; 对齐数据64

UPX0:00401DF4 sub???? eax, ecx??????????????????????? ; 对齐数据64

UPX0:00401DF6 mov???? byte ptr [edx], 80h ; '€'?????? ; name最后结尾赋值0x80

UPX0:00401DF9 cmp???? eax, 7????????????????????????? ; 对齐数据64

UPX0:00401DFC jg????? short loc_401E01

UPX0:00401DFE add???? eax, 40h ; '@'????????????????? ; 对齐数据64

UPX0:00401E01

UPX0:00401E01 loc_401E01:???????????????????????????? ; CODE XREF: UPX0:00401DFC↑j

UPX0:00401E01 add???? esi, eax

UPX0:00401E03 lea???? edi, [esp+3Ch]

UPX0:00401E07 or????? ecx, 0FFFFFFFFh

UPX0:00401E0A xor???? eax, eax

UPX0:00401E0C repne scasb

UPX0:00401E0E not???? ecx

UPX0:00401E10 dec???? ecx

UPX0:00401E11 xor???? edi, edi

UPX0:00401E13 shl???? ecx, 3????????????????????????? ; 长度*8

UPX0:00401E16 test??? esi, esi

UPX0:00401E18 mov???? [esp+esi+34h], ecx????????????? ; 添加长度数据

UPX0:00401E1C jle???? short loc_401E37

UPX0:00401E1E

UPX0:00401E1E loc_401E1E:???????????????????????????? ; CODE XREF: UPX0:00401E35↓j

UPX0:00401E1E lea???? edx, [esp+2Ch]

UPX0:00401E22 lea???? eax, [esp+edi+3Ch]

UPX0:00401E26 push??? edx

UPX0:00401E27 push??? eax

UPX0:00401E28 call??? Md5Transform??????????????????? ; md5Transform

UPX0:00401E2D add???? edi, 40h ; '@'????????????????? ; 递增64字节

UPX0:00401E30 add???? esp, 8

UPX0:00401E33 cmp???? edi, esi

UPX0:00401E35 jl????? short loc_401E1E??????????????? ; for(i=0;i < esi(对齐长度);i +=64)

UPX0:00401E37

UPX0:00401E37 loc_401E37:???????????????????????????? ; CODE XREF: UPX0:00401E1C↑j

UPX0:00401E37 mov???? ebx, [esp+2Ch]

UPX0:00401E3B lea???? ecx, [esp+28h]

UPX0:00401E3F lea???? edx, [esp+24h]

UPX0:00401E43 push??? ecx

UPX0:00401E44 lea???? eax, [esp+24h]

UPX0:00401E48 push??? edx

UPX0:00401E49 lea???? ecx, [esp+24h]

UPX0:00401E4D push??? eax

UPX0:00401E4E push??? ecx

UPX0:00401E4F lea???? edx, [esp+434h]????????????????

UPX0:00401E56 and???? ebx, 0FFFFh???????????????????? ; 将state[0]的高位抹去

UPX0:00401E5C push??? offset aLxLxLxLx??????????????? ; "%lx%lx%lx%lx"

UPX0:00401E61 push??? edx

UPX0:00401E62 mov???? [esp+44h], ebx

UPX0:00401E66 call??? _sscanf???????????????????????? ; 从code字符串中获取4个UINT数据

UPX0:00401E6B add???? esp, 18h

UPX0:00401E6E cmp???? eax, 4????????????????????????? ; 不够4个就报错

UPX0:00401E71 jz????? short loc_401E91

UPX0:00401E73 push??? 30h ; '0'

UPX0:00401E75 push??? offset aFailed????????????????? ; "Failed"

UPX0:00401E7A push??? offset aHmmmYouDonTEve????????? ; "... Hmmm, you don't even pass the first"...

UPX0:00401E7F mov???? ecx, ebp

UPX0:00401E81 call??? MfcMsgBox

UPX0:00401E86 pop???? edi

UPX0:00401E87 pop???? esi

UPX0:00401E88 pop???? ebp

UPX0:00401E89 pop???? ebx

UPX0:00401E8A add???? esp, 608h

UPX0:00401E90 retn

UPX0:00401E91 ; ---------------------------------------------------------------------------

UPX0:00401E91

UPX0:00401E91 loc_401E91:???????????????????????????? ; CODE XREF: UPX0:00401E71↑j

UPX0:00401E91 xor???? esi, esi

UPX0:00401E93 lea???? edi, [esp+1Ch]

UPX0:00401E97

UPX0:00401E97 loc_401E97:???????????????????????????? ; CODE XREF: UPX0:00401EB3↓j

UPX0:00401E97 mov???? eax, 0BADC0DEh????????????????? ; for(i=0;i < 3;i++)

UPX0:00401E9C lea???? ecx, [esi+50h]

UPX0:00401E9F cdq

UPX0:00401EA0 idiv??? ecx???????????????????????????? ; loop_cnt = 0xbadc0de / (i + 80)

UPX0:00401EA2 push??? eax

UPX0:00401EA3 push??? edi

UPX0:00401EA4 call??? Encode????????????????????????? ; 算法关键:将4个UINT做3轮ENcode

UPX0:00401EA9 add???? esp, 8

UPX0:00401EAC inc???? esi

UPX0:00401EAD add???? edi, 4

UPX0:00401EB0 cmp???? esi, 3

UPX0:00401EB3 jl????? short loc_401E97??????????????? ; for(i=0;i < 3;i++)

UPX0:00401EB5 xor???? eax, eax

UPX0:00401EB7

UPX0:00401EB7 loc_401EB7:???????????????????????????? ; CODE XREF: UPX0:00401EC9↓j

UPX0:00401EB7 mov???? edx, [esp+eax+1Ch]

UPX0:00401EBB mov???? ecx, [esp+eax+2Ch]

UPX0:00401EBF cmp???? edx, ecx

UPX0:00401EC1 jnz???? short loc_401EE9

UPX0:00401EC3 add???? eax, 4

UPX0:00401EC6 cmp???? eax, 10h

UPX0:00401EC9 jl????? short loc_401EB7

UPX0:00401ECB push??? 40h ; '@'

UPX0:00401ECD push??? offset aWelcome???????????????? ; "Welcome"

UPX0:00401ED2 push??? offset aManYouReGoodEn????????? ; "... Man, you're good enough to join COR"...

UPX0:00401ED7 mov???? ecx, ebp

UPX0:00401ED9 call??? MfcMsgBox

UPX0:00401EDE pop???? edi

UPX0:00401EDF pop???? esi

UPX0:00401EE0 pop???? ebp

UPX0:00401EE1 pop???? ebx

UPX0:00401EE2 add???? esp, 608h

UPX0:00401EE8 retn

UPX0:00401EE9 ; ---------------------------------------------------------------------------

UPX0:00401EE9

UPX0:00401EE9 loc_401EE9:???????????????????????????? ; CODE XREF: UPX0:00401EC1↑j

UPX0:00401EE9 push??? 30h ; '0'

UPX0:00401EEB push??? offset aFailed????????????????? ; "Failed"

UPX0:00401EF0 push??? offset aBetterLuckNext????????? ; "... Better luck next time ..."

UPX0:00401EF5 mov???? ecx, ebp

UPX0:00401EF7 call??? MfcMsgBox

UPX0:00401EFC pop???? edi

UPX0:00401EFD pop???? esi

UPX0:00401EFE pop???? ebp

UPX0:00401EFF pop???? ebx

UPX0:00401F00 add???? esp, 608h

UPX0:00401F06 retn

代码分析:

  • 获取name和code分别保存

  • name + strrev(name) + ProductID(项的值) + RegisterOwner(项的值);由于是win10没有注册表项, 最终结果是 name + strrev(name) + strrev(name) + strrev(name) ;

  • 初始化md5的state

  • name[-1] = 0x80 ;数据对齐64字节,存储len * 8

  • 循环Md5Tramsform

  • 保留state[0] 低16位,关键跳比较的就是state[0]的数据

  • 读取code中的4个UINT

  • 分别对 UINT[0] UINT[1];UINT[1]UINT[2];UINT[2]UINT[3] 运算

  • 比较 UINT[0] 和 state[0] 如果相等则成功;

Encode函数

关键函数Encode函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

UPX0:00401B90 Encode proc near??????????????????????? ; CODE XREF: UPX0:00401EA4↓p

UPX0:00401B90

UPX0:00401B90 arg_0= dword ptr? 4

UPX0:00401B90 arg_4= dword ptr? 8

UPX0:00401B90

UPX0:00401B90 mov???? eax, [esp+arg_0]

UPX0:00401B94 push??? ebx

UPX0:00401B95 mov???? ebx, [esp+4+arg_4]

UPX0:00401B99 push??? esi

UPX0:00401B9A mov???? esi, [eax]

UPX0:00401B9C push??? edi

UPX0:00401B9D mov???? edi, [eax+4]

UPX0:00401BA0 test??? ebx, ebx

UPX0:00401BA2 jbe???? short loc_401C15

UPX0:00401BA4 push??? ebp???????????????????????????? ; edi = 32位UINT

UPX0:00401BA4???????????????????????????????????????? ; esi = 32位UINT

UPX0:00401BA5

UPX0:00401BA5 loc_401BA5:???????????????????????????? ; CODE XREF: Encode+7E↓j

UPX0:00401BA5 mov???? ebp, edi??????????????????????? ; for(i=0;i<loop_cnt;i++)

UPX0:00401BA5???????????????????????????????????????? ; 第一步就是实现2个UINT的循环左移1

UPX0:00401BA7 mov???? ecx, 1

UPX0:00401BAC shr???? ebp, 1Fh

UPX0:00401BAF mov???? [esp+10h+arg_4], ebp??????????? ; 取高32位最高位,保存一下

UPX0:00401BB3 mov???? eax, esi

UPX0:00401BB5 mov???? edx, edi

UPX0:00401BB7 xor???? ebp, ebp

UPX0:00401BB9 call??? __allshl??????????????????????? ; 2个UINT实现左移1

UPX0:00401BBE mov???? ecx, [esp+10h+arg_4]??????????? ; 再将保存的的高32位的最高一位给低32位的最低位,实现循环左移

UPX0:00401BC2 or????? ebp, edx

UPX0:00401BC4 or????? ecx, eax

UPX0:00401BC6 xor???? edx, edx

UPX0:00401BC8 mov???? esi, ecx??????????????????????? ; 循环左移结束

UPX0:00401BCA mov???? ecx, 0Bh??????????????????????? ; 后面就是取低32位的第2 13 31位做亦或

UPX0:00401BCF mov???? eax, esi

UPX0:00401BD1 mov???? edi, ebp

UPX0:00401BD3 and???? eax, 4????????????????????????? ; 取低32位数据 2

UPX0:00401BD6 call??? __allshl??????????????????????? ; 循环做移动1111 + 2 = 13

UPX0:00401BDB mov???? ecx, esi

UPX0:00401BDD xor???? ebp, ebp

UPX0:00401BDF and???? ecx, 2000h????????????????????? ; 取低32位数据 13

UPX0:00401BE5 xor???? edx, ebp

UPX0:00401BE7 xor???? eax, ecx??????????????????????? ; 然后 亦或

UPX0:00401BE9 mov???? ecx, 12h??????????????????????? ; 循环做移动18位? 13 + 18 = 31

UPX0:00401BEE call??? __allshl

UPX0:00401BF3 mov???? ecx, esi

UPX0:00401BF5 xor???? edx, ebp

UPX0:00401BF7 and???? ecx, 80000000h????????????????? ; 取低32位数据 31

UPX0:00401BFD xor???? eax, ecx??????????????????????? ; eax = eax ^ 31位的值

UPX0:00401BFF mov???? ecx, 1

UPX0:00401C04 call??? __allshl??????????????????????? ; 左移动一位将,亦或结果存入edx

UPX0:00401C09 xor???? esi, eax??????????????????????? ; eax 不管是0还是0x8000000左移1位后总是0

UPX0:00401C0B xor???? edi, edx??????????????????????? ; 高32位的最后一位和亦或结果做亦或

UPX0:00401C0D dec???? ebx

UPX0:00401C0E jnz???? short loc_401BA5??????????????? ; for(i=0;i<loop_cnt;i++)

UPX0:00401C0E???????????????????????????????????????? ; 第一步就是实现2个UINT的循环左移1

UPX0:00401C10 mov???? eax, [esp+10h+arg_0]

UPX0:00401C14 pop???? ebp

UPX0:00401C15

UPX0:00401C15 loc_401C15:???????????????????????????? ; CODE XREF: Encode+12↑j

UPX0:00401C15 mov???? [eax], esi

UPX0:00401C17 mov???? [eax+4], edi

UPX0:00401C1A pop???? edi

UPX0:00401C1B pop???? esi

UPX0:00401C1C pop???? ebx

UPX0:00401C1D retn

UPX0:00401C1D Encode endp

代码解读,直接c代码把

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

// 编码所用

void AllShl(unsigned int* low32, unsigned int* high32, unsigned int left) {

????unsigned int _low32, _high32, lowLeft;

????if (left < 32)

????{

????????_low32 = *low32;

????????_high32 = *high32;

????????lowLeft = _low32 >> (32 - left);

????????_high32 = _high32 << left;

????????_low32 = _low32 << left;

????????_high32 = _high32 | lowLeft;

????????*low32 = _low32;

????????*high32 = _high32;

????}

}

void Encode(unsigned int* low32, unsigned* high32, unsigned int loop) {

????unsigned int b2,h31,tHigh;

????for (unsigned int i = 0; i < loop; loop--) {

????????// 第一步就是循环左移一位,高32位最高位会溢出,所以源程序先保存最高位,然后,补到低32位的最低为

????????// 其实就是一个圈

????????// 自己实现了一个圈

????????h31 = (*high32) >> 31;

????????AllShl(low32, high32, 1);

????????*low32 = *low32 | h31;

????????tHigh = 0;

????????b2 = *low32 & 4;??????????? // low32取第2位

????????AllShl(&b2, &tHigh, 11);??? // 左移11位 + 原来的2位 = 13位

????????b2 = b2 ^ (*low32 & 0x2000);// 第二位和第13位亦或

?????????

????????AllShl(&b2, &tHigh, 18);?? // 左移18位 + 原来的13位 = 31位

????????b2 = b2 ^ (*low32 & 0x80000000);// 第二位和第31位亦或

????????AllShl(&b2, &tHigh, 1);

????????*low32 = *low32 ^ b2;?????????? // b2 始终等于0

????????*high32 = *high32 ^ tHigh;

????}

}

简化后的Encode

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

void Encode(unsigned int* low32, unsigned* high32, unsigned int loop) {

????unsigned int h31, b2, b13, b31;

????for (unsigned int i = 0; i < loop; loop--) {

????????// 第一步就是循环左移一位,高32位最高位会溢出,所以源程序先保存最高位,然后,补到低32位的最低为

????????// 其实就是一个圈

????????// 自己实现了一个圈

????????h31 = (*high32) >> 31;

????????AllShl(low32, high32, 1);

????????*low32 = *low32 | h31;

????????// 其实后面的就是取低32位中第 2,13,31位的值进行亦或;然后和高32位最低为进行亦或

????????// 简化得到

????????b2 = ((*low32) & 4) >> 2;???????????? // 取2位

????????b13 = ((*low32) & 0x2000) >> 13;????? // 取13位

????????b31 = ((*low32) & 0x80000000) >> 31;? // 取31位

?????????

????????b2 = b2 ^ b13 ^ b31;

????????*high32 = *high32 ^ b2;

????}

}

简化后其实就2步骤,根据低32位还原高32位;然后循环右移1位

Decode代码可得

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

// 解码所用

void AllShr(unsigned int* low32, unsigned int* high32, unsigned int right) {

????unsigned int _low32, _high32, highRight;

????if (right < 32)

????{

????????_low32 = *low32;

????????_high32 = *high32;

????????highRight = _high32 << (32 - right);

????????_high32 = _high32 >> right;

????????_low32 = _low32 >> right;

????????_low32 = _low32 | highRight;

????????*low32 = _low32;

????????*high32 = _high32;

????}

}

void Decode(unsigned int* low32, unsigned* high32, unsigned int loop) {

????unsigned int l1, b2, b13, b31;

????for (unsigned int i = 0; i < loop; loop--) {

????????// 第一步还原高32位的最低位

????????// 还是求低32位的第 2 13 31 位的亦或值,根据亦或特性 还原高32位数值

????????b2 = ((*low32) & 4) >> 2;???????????? // 取2位

????????b13 = ((*low32) & 0x2000) >> 13;????? // 取13位

????????b31 = ((*low32) & 0x80000000) >> 31;? // 取31位

????????b2 = b2 ^ b13 ^ b31;

????????*high32 = *high32 ^ b2;

????????// 第二步右旋转1位

????????l1 = *low32 & 1;??????????? // 取low32最低位

????????AllShr(low32, high32, 1);?? // 右移动1位

????????l1 = l1 << 31;

????????*high32 = *high32 | l1;???? // 将l1补到高32位上

????}

}

验证可行性

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

unsigned int a[4];

a[0] = 0x11111111;

a[1] = 0x22222222;

a[2] = 0x33333333;

a[3] = 0x44444444;

printf("Org?? : %08lx %08lx %08lx %08lx\n", a[0], a[1], a[2], a[3]);

for (i = 0; i < 3; i++) {

????base = 0x0BADC0DE / (i + 0x50);

????printf("%d loop = %lx\n", i, base);

????Encode(a + i, a + i + 1, base);

}

printf("Encode: %08lx %08lx %08lx %08lx\n", a[0], a[1], a[2], a[3]);

for (i = 2; i >= 0; i--) {

????base = 0x0BADC0DE / (i + 0x50);

????printf("%d loop = %lx\n",i, base);

????Decode(a + i, a + i + 1, base);

}

printf("Decode: %08lx %08lx %08lx %08lx\n", a[0], a[1], a[2], a[3]);

return;

验证结果

1

2

3

4

5

6

7

8

9

Org?? : 11111111 22222222 33333333 44444444

0 loop = 255f35

1 loop = 24e918

2 loop = 2475dd

Encode: 647577db 5250c59b 90dc6469 57a10cc3

2 loop = 2475dd

1 loop = 24e918

0 loop = 255f35

Decode: 11111111 22222222 33333333 44444444

keygen

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "md5.h"

char* _strrev(char* s)

{

????char* h = s;

????char* t = s;

????char ch;

????while (*t++) {};

????t--;

????t--;

????while (h < t)

????{

????????ch = *h;

????????*h++ = *t;

????????*t-- = ch;

????}

????return(s);

}

// 解码所用

void AllShr(unsigned int* low32, unsigned int* high32, unsigned int right) {

????unsigned int _low32, _high32, highRight;

????if (right < 32)

????{

????????_low32 = *low32;

????????_high32 = *high32;

????????highRight = _high32 << (32 - right);

????????_high32 = _high32 >> right;

????????_low32 = _low32 >> right;

????????_low32 = _low32 | highRight;

????????*low32 = _low32;

????????*high32 = _high32;

????}

}

void Decode(unsigned int* low32, unsigned* high32, unsigned int loop) {

????unsigned int l1, b2, b13, b31;

????for (unsigned int i = 0; i < loop; loop--) {

????????// 第一步还原高32位的最低位

????????// 还是求低32位的第 2 13 31 位的亦或值,根据亦或特性 还原高32位数值

????????b2 = ((*low32) & 4) >> 2;???????????? // 取2位

????????b13 = ((*low32) & 0x2000) >> 13;????? // 取13位

????????b31 = ((*low32) & 0x80000000) >> 31;? // 取31位

????????b2 = b2 ^ b13 ^ b31;

????????*high32 = *high32 ^ b2;

????????// 第二步右旋转1位

????????l1 = *low32 & 1;??????????? // 取low32最低位

????????AllShr(low32, high32, 1);?? // 右移动1位

????????l1 = l1 << 31;

????????*high32 = *high32 | l1;

????}

}

void main()

{

????int i, len,buffLen,lenOffset;

????unsigned char* data;

????char name[128] = "";

????char names[16] = "";

????unsigned int base;

????MD5_CTX ctx;

????printf("pls,input 'name'>");

????scanf("%s", name);

?????

????buffLen = strlen(name) * 4 + 1 + 8;?????? // name + 3次name反转 + 一位字符结束的特殊符号0x80,4字节int + 4字节空白

????buffLen = (buffLen + 0x40) / 0x40 * 0x40; // 64对齐

????lenOffset = buffLen - 8;????????????????? // 最后8字节位置是int=长度<<3

????data = malloc(buffLen);

????memset(data, 0, buffLen);

????printf("name:%s\n", name);

????strcpy(data, name);

????strcpy(names, name);

????_strrev(names);

????for (i = 0; i < 3; i++)

????{

????????strcat(data, names); // 因为win10没有注册表项,结果就是这样子

????}

????printf("data:%s\n", data);

????len = strlen(data);

????data[len] = 0x80;

????len += 1;

????*(unsigned int*)(data + lenOffset) = len * 8;

????MD5Init(&ctx);

????for ( i = 0; i < buffLen; i+=64)

????{

????????MD5Transform(ctx.state, (unsigned char *)data + i);

????}

?????

????printf("md5 : %08lx %08lx %08lx %08lx\n", ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3]);

????ctx.state[0] = ctx.state[0] & 0xffff;

????printf("md5 : %08lx %08lx %08lx %08lx\n", ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3]);

????for (i = 2; i >= 0; i--) {

????????base = 0x0BADC0DE / (i + 0x50);

????????printf("%d loop = %lx\n", i, base);

????????Decode(ctx.state + i, ctx.state + i + 1, base);

????}

????printf("code : %08lx %08lx %08lx %08lx\n", ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3]);

?????

????return;

}

几组组NS供验证:

helloworld : 7db37660 ae4c5d05 d2783eea 1d6514f2

pediy.com : b3f21c39 e8ca4483 4146d6f6 5644545b
?

?

文章来源:https://blog.csdn.net/wei_java144/article/details/135694968
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。