广告位联系
返回顶部
分享到

IDM 6.40.11.2 弹窗的完美解决思路

相关技巧 来源:互联网 作者:佚名 发布时间:2023-01-07 21:33:44 人浏览
摘要

IDM 6.40.11.2 弹窗的解决思路 前言 在IDM官方下载了IDM的30天试用版。 装好后,找了一个和谐工具。运行和谐工具后,看IDM关于那里,已经是全功能版本。 美中不足的是,IDM运行一段时间

IDM 6.40.11.2 弹窗的解决思路

前言

在IDM官方下载了IDM的30天试用版。

装好后,找了一个和谐工具。运行和谐工具后,看IDM关于那里,已经是全功能版本。

美中不足的是,IDM运行一段时间,就会弹出neg窗口,说文件被修改,最好是去官网下载原版的提示。

我这的弹框如下:

文本提示信息如下:

---------------------------
IDM is corrupt
---------------------------
The main IDM executive file is damaged. It's possible that it was infected with a virus.

Please download the latest version of IDM from our web site, and install it over your current version. Just run downloaded IDM installer, and it will replace the damaged files. Do not worry, because all downloads and IDM settings will not be affected
---------------------------
确定   
---------------------------

虽然是不影响使用,但是不断的要关掉neg窗口会让人疯掉的,弄不好要得强迫症:(

查看IDMan.exe的属性,看到版本为 6.40.11.2

在网上找了一下,好像没有太好的方法去掉neg窗口。
有些方法是针对旧版的,针对这个新版不好使。

实验环境

win10 21H2 + IDA7.7.220118

确定弹窗的所有者

这个neg弹窗通过spy++看,是IDM主程序弹出的,并不是调用的外部exe.

开始调试

那就只能通过无源码调试,学习研究,撸清弹窗的逻辑。

用IDA载入IDMan.exe,看调试信息,可以知道IDM6.40.11是用vs2008中的MFC写的程序。

看到IDM目录下并没有MFCDLL, 知道IDM是静态使用MFC库的。

尝试用IDAx86将IDMan.exe带着跑起来,看看有没有机会将neg窗口搞掉。

IDM并没有做明显的反调试处理,用IDA带着IDM跑起来,功能都是正常的。作者比较温和。

IDM弹出neg窗口是随机的,一天反正要弹那么几次。弹框后,按确定键,还会去IDM官网下载页面. 次数多了,真是不耐其烦啊…
还不如作者不给老百姓用,这样还省心些。

作者为的就是让和谐版的用户心烦,然后买原版省心。
关键是作者忽略了像我这种喜欢DIY的用户,这咋弄?

等了一下午,终于等到IDM弹neg窗口了, 美滋滋。

点击neg窗口的确定按钮,打开了网页,去了IDM站点。url如下:

https://www.internetdownloadmanager.com/download3.html?lng=chn2

在串参考中查找 ?lng=

找到了几个,唯一和这个url符合的字符串如下:

1

2

.rdata:00CF7164 aSLngS_0        db '%s?lng=%s',0        ; DATA XREF: sub_AF6E90+D51↑o

.rdata:00CF7164                                         ; sub_AFA1A0+D51↑o ...

查找 aSLngS_0 的调用者就能找到拼url的地方,这个地方和弹窗是一个逻辑流。

调用点一共有3处

debug1

1

.text:00AF7BE1                 push    offset aSLngS_0 ; "%s?lng=%s"

debug2

1

.text:00AFAEF1                 push    offset aSLngS_0 ; "%s?lng=%s"

debug3

1

.text:00C40B0C                 push    offset aSLngS_0 ; "%s?lng=%s"

主dlg虚表位置

由debug1查找调用点,逐级回溯查找调用点,找到了主Dlg的虚表。

1

2

3

4

5

6

7

8

9

10

.rdata:00CF6719                 align 10h

.rdata:00CF6720                 dd offset ??_R4CDownloaderDlg@@6B@ ; const CDownloaderDlg::`RTTI Complete Object Locator'

.rdata:00CF6724 ; const CDownloaderDlg::`vftable'

.rdata:00CF6724 ??_7CDownloaderDlg@@6B@ dd offset sub_C689EF

.rdata:00CF6724                                         ; DATA XREF: sub_ADD890+40↑o

.rdata:00CF6724                                         ; CRecordset::~CRecordset(void)+30↑o

.rdata:00CF6728                 dd offset sub_AE0980

.rdata:00CF672C                 dd offset nullsub_1

.rdata:00CF6730                 dd offset unknown_libname_51 ; MFC 3.1-14.0 32bit

.rdata:00CF6734                 dd offset ?OnFinalRelease@CWnd@@UAEXXZ ; CWnd::OnFinalRelease(void)

根据自己写MFC程序的经验,就在这些虚函数中找,就能看到判断程序损坏的逻辑。

看了一圈,没看到逻辑。我只看了顶层函数,子函数调用没看。应该是在那些子函数中。

换个方法调试 - 在这3处启动网页的地方下断点

这3处下断点(F2), 然后用IDA带着IDM跑起来。

等了3个小时,IDM终于弹框了。点击确认,IDA下的断点断住了。

1

2

3

4

5

6

7

8

9

.text:0050AEEC push    ecx                             ; ArgList

.text:0050AEED lea     edx, [esp+1F8h+var_1D0]

.text:0050AEF1 push    offset aSLngS_0                 ; "%s?lng=%s" // break here

.text:0050AEF6 push    edx                             ; int

.text:0050AEF7 call    sub_492F80

.text:0050AEFC add     esp, 1Ch

.text:0050AEFF mov     byte ptr [esp+1E4h+var_4], bl

.text:0050AF06 lea     ecx, [esp+1E4h+var_1CC]         ; void *

.text:0050AF0A call    sub_492570

因为程序是动态装载的,首地址的段不一样。比较地址后面的4个字节,可以知道是debug2处的url.

如果查看代码到了非当前IP处,先回到当前IP处的代码。

选择当前线程

在栈窗口跳到ESP

跟随ESP的反汇编。

这时,就回到了断住的第一现场。如果自己F7单步过,当前现场就在断点下面2,3行。

打开函数调用链窗口

可以看到当前被断住的代码的调用链。

可知,当前代码在sub_50A1A0中。

最近调用过的一个函数是sub_491980

复制保存当前的调用链为文本,用于分析。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

.text:0050AD76  call    sub_491980

.text:0050AE08  call    esi ; GetDesktopWindow

.text:0050AE0B  call    sub_4FDB50

.text:0050AE2B  call    sub_4911F0

.text:0050AE43  call    sub_4930C0

.text:0050AE8D  call    sub_4921B0

.text:0050AEA1  call    _wcsrchr

.text:0050AEC1  call    _wcsrchr

.text:0050AED6  call    sub_492A70

.text:0050AEF7  call    sub_492F80

.text:0050AF0A  call    sub_492570

.text:0050AF1B  call    sub_4911F0

.text:0050AF25  call    esi ; GetDesktopWindow

.text:0050AF28  call    sub_53BEB0

.text:0050AF42  call    ds:SetTimer

.text:0050AF54  call    sub_492570

.text:0050AF68  call    sub_4911F0

.text:0050AF8B  call    @__security_check_cookie@4; __security_check_cookie(x)

.text:006CEBAE  call    @__security_check_cookie@4; __security_check_cookie(x)

.text:006CEBBB  call    @__security_check_cookie@4; __security_check_cookie(x)

回到当前IP处的代码,用图形方式查看代码实现,逻辑看的清楚。
同一逻辑的代码都用在一个图形框里面,跳转看的清楚。

鼠标左键拖动 + 鼠标中键滚动,向上看代码逻辑。咋走到这里来的?

再看看这个函数的图形调用链。

现在就可以去查fn_msg_proc_sub_B07090中,调用sub_50A1A0的调用点。

顺着调用链看代码时,发现疑似弹窗实现。

.text:0050AE0B call    sub_4FDB50

.text:004FDC1E call    ds:MessageBoxW

在 MessageBoxW调用处下断点看看。

1

2

.idata:006F972C ; int (__stdcall *MessageBoxW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)

.idata:006F972C MessageBoxW dd offset user32_MessageBoxW

现在有3个url字符串拼串的断点,剩下断点都是MessageBoxW的断点,已经跑起来了。等弹框。

等到弹框断点断住

晚上本本没关,等到了早上10点钟左右。IDA被弹窗操作断下来了。
等了12+小时,终于等到弹框断点被断住。作者可能不知道我这么有耐心陪他玩。

1

2

3

4

5

6

7

8

9

10

11

12

13

.text:004FDC16

.text:004FDC16 loc_4FDC16:

.text:004FDC16 mov     edx, [esp+34h+uType]

.text:004FDC1A push    edx             ; uType

.text:004FDC1B push    eax             ; lpCaption

.text:004FDC1C push    ebp             ; lpText

.text:004FDC1D push    edi             ; hWnd

.text:004FDC1E call    ds:MessageBoxW // break here

.text:004FDC24 mov     esi, eax

.text:004FDC26 mov     byte ptr [esp+34h+var_4], bl

.text:004FDC2A lea     ecx, [esp+34h+var_20] ; void *

.text:004FDC2E call    sub_492570

.text:004FDC33 jmp     short loc_4FDC55

这个断点在 .text:004FDB50 sub_4FDB50 proc near 函数中

偏移 = 4FDC1E - 4FDB50 = 206 = 0xCE

按x键时,可以看到这个断点为

1

p   sub_4FDB50+CE   call    ds:MessageBoxW

栈窗口内容

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

// 栈是向上生长的

// 每多调用一个函数,地址就减少

// 当断下时,栈地址 = 063DF674

// 代码为

.text:004FDC16 mov     edx, [esp+34h+uType]

.text:004FDC1A push    edx             ; uType

.text:004FDC1B push    eax             ; lpCaption

.text:004FDC1C push    ebp             ; lpText

.text:004FDC1D push    edi             ; hWnd

.text:004FDC1E call    ds:MessageBoxW // 栈地址 = 063DF674

 

// 此时,按F7步入MessageBoxW,栈地址就变为063DF670,栈地址减小了

 

063DF670  004FDC24  neg_msgbox_sub_4FDB50+D4

063DF674  00010010  // 断下时的栈顶

063DF678  0394E340  debug080:0394E340

063DF67C  03949690  debug080:03949690

063DF680  00041030 

063DF684  BB18CB49 

063DF688  00000035 

063DF68C  76B89F90  USER32:user32_GetDesktopWindow

063DF690  00000000 

063DF694  00000C8A 

063DF698  0394AF70  debug080:0394AF70

063DF69C  03949690  debug080:03949690

063DF6A0  063D0000 

063DF6A4  0000000F 

063DF6A8  BB18CB59 

063DF6AC  063DF8A4  debug286:063DF8A4

063DF6B0  006E09A0  sub_5CF400:SEH_46DB50

063DF6B4  00000001 

063DF6B8  0050AE10  sub_50A1A0+C70

063DF6BC  00010010 

063DF6C0  0394E340  debug080:0394E340

063DF6C4  063DF700  debug286:063DF700

063DF6C8  00041030 

063DF6CC  BB18CB11 

063DF6D0  011E7470  debug011:011E7470

063DF6D4  0393BBE0  debug080:0393BBE0

063DF6D8  063DF934  debug286:063DF934

063DF6DC  00000C50 

063DF6E0  FFFFFFFE 

063DF6E4  012B0000  debug030:012B0000

063DF6E8  4014006A 

063DF6EC  00000000 

063DF6F0  772A0000  ntdll:772A0000

063DF6F4  0394E340  debug080:0394E340

063DF6F8  00000000 

063DF6FC  00000157 

063DF700  204D4449 

063DF704  63207369 

063DF708  7572726F  Crypt32:crypt32_I_CryptInstallOssGlobal+546F

063DF70C  A2007470 

063DF710  70747468 

063DF714  772F2F3A  ntdll:ntdll_RtlGetThreadPreferredUILanguages+18A

063DF718  692E7777 

063DF71C  7265746E 

063DF720  6474656E 

063DF724  6C6E776F 

063DF728  6D64616F 

063DF72C  67616E61  dcomp:67616E61

063DF730  632E7265 

063DF734  642F6D6F 

063DF738  6C6E776F 

063DF73C  3264616F 

063DF740  6D74682E 

063DF744  0000006C 

063DF748  20656854 

063DF74C  6E69616D 

063DF750  4D444920 

063DF754  65786520 

063DF758  69747563 

063DF75C  66206576 

063DF760  20656C69 

063DF764  64207369 

063DF768  67616D61  dcomp:67616D61

063DF76C  202E6465 

063DF770  73277449  mswsock:73277449

063DF774  736F7020 

063DF778  6C626973 

063DF77C  68742065  COMCTL32:comctl32_Ordinal234+BEE5

063DF780  69207461 

063DF784  61772074 

063DF788  6E692073 

063DF78C  74636566  windows.storage:74636566

063DF790  77206465  COMDLG32:77206465

063DF794  20687469 

063DF798  69762061 

063DF79C  2E737572 

063DF7A0  0A0D0A0D 

063DF7A4  61656C50 

063DF7A8  64206573 

063DF7AC  6C6E776F 

063DF7B0  2064616F 

063DF7B4  20656874 

063DF7B8  6574616C 

063DF7BC  76207473  SETUPAPI:76207473

063DF7C0  69737265 

063DF7C4  6F206E6F 

063DF7C8  44492066 

063DF7CC  7266204D 

063DF7D0  6F206D6F 

063DF7D4  77207275  COMDLG32:77207275

063DF7D8  73206265  RASAPI32:73206265

063DF7DC  2C657469 

063DF7E0  646E6120 

063DF7E4  736E6920 

063DF7E8  6C6C6174 

063DF7EC  20746920 

063DF7F0  7265766F 

063DF7F4  756F7920  Crypt32:crypt32_RegCreateHKCUKeyExU+8F20

063DF7F8  75632072  KERNEL32:kernel32_WakeConditionVariable+1E8C

063DF7FC  6E657272 

063DF800  65762074 

063DF804  6F697372 

063DF808  4A202E6E 

063DF80C  20747375 

063DF810  206E7572 

063DF814  6E776F64 

063DF818  64616F6C 

063DF81C  49206465 

063DF820  69204D44 

063DF824  6174736E 

063DF828  72656C6C 

063DF82C  6E61202C 

063DF830  74692064  windows.storage:74692064

063DF834  6C697720 

063DF838  6572206C 

063DF83C  63616C70  schannel:schannel_SpLsaModeInitialize+12420

063DF840  68742065  COMCTL32:comctl32_Ordinal234+BEE5

063DF844  61642065 

063DF848  6567616D 

063DF84C  69662064 

063DF850  2E73656C 

063DF854  206F4420 

063DF858  20746F6E 

063DF85C  72726F77 

063DF860  62202C79 

063DF864  75616365  KERNEL32:kernel32_Wow64Transition+4331

063DF868  61206573 

063DF86C  64206C6C 

063DF870  6C6E776F 

063DF874  7364616F 

063DF878  646E6120 

063DF87C  4D444920 

063DF880  74657320  windows.storage:74657320

063DF884  676E6974  dcomp:dcomp_DllGetClassObject+31B04

063DF888  69772073 

063DF88C  6E206C6C 

063DF890  6220746F 

063DF894  66612065 

063DF898  74636566  windows.storage:74636566

063DF89C  01006465 

063DF8A0  BB18CB21 

063DF8A4  063DF928  debug286:063DF928

063DF8A8  006CEB9C  sub_506E90:SEH_47A1A0

063DF8AC  00000000 

063DF8B0  00682640  _AfxThreadEntry(void *)+DA

063DF8B4  00000000 

063DF8B8  BB18C4F5 

063DF8BC  006AD07B  _threadstartex(x)

063DF8C0  0394E930  debug080:0394E930

063DF8C4  0394E930  debug080:0394E930

063DF8C8  00000000 

063DF8CC  0078458C  .rdata:const CWnd::`vftable'

063DF8D0  00000001 

063DF8D4  00000000 

063DF8D8  00000000 

063DF8DC  00000000 

063DF8E0  00000001 

063DF8E4  00000000 

063DF8E8  012C57D8  debug030:012C57D8

063DF8EC  00000000 

063DF8F0  D378BE00 

063DF8F4  00000000 

063DF8F8  00000000 

063DF8FC  007844FC  .rdata:const CWnd::XAccessible::`vftable'

063DF900  00784570  .rdata:const CWnd::XAccessibleServer::`vftable'

063DF904  00000000 

063DF908  00000000 

063DF90C  00000000 

063DF910  00000000 

063DF914  00000000 

063DF918  00000000 

063DF91C  00000000 

063DF920  0393BBE0  debug080:0393BBE0

063DF924  063DF8B8  debug286:063DF8B8

063DF928  063DF95C  debug286:063DF95C

063DF92C  006EAD0D  _AfxThreadEntry(void *):loc_6EAD0D

063DF930  00000000 

063DF934  063DF96C  debug286:063DF96C

063DF938  006AD055  __callthreadstartex+1B

063DF93C  011E7470  debug011:011E7470

063DF940  BB18C4AD 

063DF944  006AD07B  _threadstartex(x)

063DF948  0394E930  debug080:0394E930

063DF94C  0394E930  debug080:0394E930

063DF950  063DF940  debug286:063DF940

063DF954  063DF940  debug286:063DF940

063DF958  063DF9D4  debug286:063DF9D4

063DF95C  063DF9D4  debug286:063DF9D4

063DF960  006A69B0  SEH_6337D0

063DF964  BD59D039 

063DF968  00000000 

063DF96C  063DF978  debug286:063DF978

063DF970  006AD0FD  .text:006AD0FD

063DF974  006AD07B  _threadstartex(x)

063DF978  063DF988  debug286:063DF988

063DF97C  755AFA29  KERNEL32:kernel32_BaseThreadInitThunk+19

063DF980  0394E930  debug080:0394E930

063DF984  755AFA10  KERNEL32:kernel32_BaseThreadInitThunk

063DF988  063DF9E4  debug286:063DF9E4

063DF98C  77307A7E  ntdll:ntdll_RtlGetAppContainerNamedObjectPath+11E

063DF990  0394E930  debug080:0394E930

063DF994  D378BF44 

063DF998  00000000 

063DF99C  00000000 

063DF9A0  0394E930  debug080:0394E930

063DF9A4  00000000 

063DF9A8  00000000 

063DF9AC  00000000 

063DF9B0  00000000 

063DF9B4  00000000 

063DF9B8  00000000 

063DF9BC  00000000 

063DF9C0  00000000 

063DF9C4  00000000 

063DF9C8  00000000 

063DF9CC  063DF994  debug286:063DF994

063DF9D0  00000000 

063DF9D4  063DF9EC  debug286:063DF9EC

063DF9D8  7731AD20  ntdll:ntdll_wcstombs+70

063DF9DC  A27F8F80 

063DF9E0  00000000 

063DF9E4  063DF9F4  debug286:063DF9F4

063DF9E8  77307A4E  ntdll:ntdll_RtlGetAppContainerNamedObjectPath+EE

063DF9EC  FFFFFFFF 

063DF9F0  77328A28  ntdll:ntdll_RtlCaptureContext+E8

063DF9F4  00000000 

063DF9F8  00000000 

063DF9FC  006AD07B  _threadstartex(x)

063DFA00  0394E930  debug080:0394E930

弹窗后,F7/F8 单步,回到了 sub_50A1A0

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

unsigned int __cdecl fn_show_neg_wnd_sub_50A1A0(void *a1)

{

// 这个函数功能

// 给弹框内容赋值,一个一个字节的赋值,翻译字符串成宽字符串。让调试者在字符串表中,找不到现成的字符串。

// 然后弹框

// ...

v14 = v7;

  DesktopWindow = GetDesktopWindow();

  neg_msgbox_sub_4FDB50(DesktopWindow, v14, v24, 0x41030u);

  if ( a1 )

  {

    v27 = -1;

    fn_delete_sub_4911F0();

    return 1;

  }

  else

  {

    sub_4930C0(ArgList);

    ...

        v15 = v16;

    v13 = GetDesktopWindow();

    sub_53BEB0(v13, v15); // 这里疑似打开下载网页

    if ( hWnd )

      SetTimer(hWnd, 0x26u, 0x36EE80u, 0); // 这个定时器(0x26)应该就是neg窗口检测的定时器。

      // 0x36EE80u = 3600000 = 3600秒 = 60分钟 = 1小时

      // 这个定时器一个小时的,而且这个定时器1小时时间到后,也不是每次都弹框。

      // 可以考虑在1小时定时器中,不干活。

    LOBYTE(v27) = 0;

    fn_free_sub_492570(&v16);

    v27 = -1;

    fn_delete_sub_4911F0();

    return 0;

  }

单步出来,到MFC线程函数操作中了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

  if ( v6 )

  {

    v7 = v6(v1[13]); // 执行 fn_show_neg_wnd_sub_50A1A0

  }

  else

  {

    v8 = (*(int (__thiscall **)(_DWORD *))(*v1 + 80))(v1) == 0;

    v9 = *v1;

    if ( v8 )

      v7 = (*(int (__thiscall **)(_DWORD *))(v9 + 104))(v1);

    else

      v7 = (*(int (__thiscall **)(_DWORD *))(v9 + 84))(v1);

  }

  v10 = v7;

  CWnd::Detach((CWnd *)v11);

  AfxEndThread(v10, 1);

}

通过单步,已经知道IDM是用26号定时器(触发时间1个小时)来弹neg窗口和neg URL.

neg线程函数为 fn_show_neg_wnd_sub_50A1A0

停掉IDA调试,回分析状态。

在函数列表中过滤出 fn_show_neg_wnd_sub_50A1A0

查找 fn_show_neg_wnd_sub_50A1A0的调用点

可以看到只有一处,双击过去瞧瞧。

1

2

3

4

5

6

7

8

9

10

11

12

13

.text:0051D68F

.text:0051D68F loc_51D68F:                             ; CODE XREF: fn_msg_proc_sub_B07090+2A1A↑j

.text:0051D68F                                         ; DATA XREF: .text:jpt_519AAA↓o

.text:0051D68F                 push    0               ; jumptable 00519AAA case 5355

.text:0051D691                 push    0               ; unsigned int

.text:0051D693                 push    0               ; StackSize

.text:0051D695                 push    0               ; int

.text:0051D697                 push    0               ; void *

.text:0051D699                 push    offset fn_show_neg_wnd_sub_50A1A0 ; unsigned int (__cdecl *)(void *)

.text:0051D69E                 call    ?AfxBeginThread@@YGPAVCWinThread@@P6AIPAX@Z0HIKPAU_SECURITY_ATTRIBUTES@@@Z ; AfxBeginThread(uint (*)(void *),void *,int,uint,ulong,_SECURITY_ATTRIBUTES *)

.text:0051D6A3                 mov     eax, 1

.text:0051D6A8                 wait

.text:0051D6A9                 jmp     loc_51F405

看到了不? 这里起了一个neg线程。

往上拉,看看这个起neg线程的函数的整体含义。

这是一个消息处理函数啊

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

int __thiscall fn_msg_proc_sub_B07090(int this, UINT wParam, LPARAM a3)

{

// CWnd::OnCommand 处理

 

  LPARAM v4; // ecx

 // ...

  

  

 // 消息ID = 0x14EB

 case 0x14EBu:

        AfxBeginThread(fn_show_neg_wnd_sub_50A1A0, 0, 0, 0, 0, 0); // 这里启动neg线程

        return 1;

      case 0x14ECu:

        if ( sub_4E6AE0(v384, v385) )

          return 1;

        v247 = *(WPARAM **)(this + 492);

        if ( !v247 )

          return 1;

LABEL_862:

        sub_4BDBF0(0x111u, *v247, 0);

        return 1;

      default:

        return CWnd::OnCommand((CWnd *)this, wParam, lParam);

    }

  

 // ...

 LABEL_862:

        sub_4BDBF0(0x111u, *v247, 0);

        return 1;

      default:

        return CWnd::OnCommand((CWnd *)this, wParam, lParam);

    }

  }

  if ( wParam != 10239 )

    return CWnd::OnCommand((CWnd *)this, wParam, lParam);

  sub_4FB3F0(1);

  return 1;

}

已经看到 // 消息ID = 0x14EB 引起建立neg线程

用图形模式看

1

2

3

4

5

6

7

8

9

10

11

12

loc_51D68F:             ; jumptable 00519AAA case 5355

; 0x14EB is 5355

push    0

push    0               ; unsigned int

push    0               ; StackSize

push    0               ; int

push    0               ; void *

push    offset fn_show_neg_wnd_sub_50A1A0 ; unsigned int (__cdecl *)(void *)

call    ?AfxBeginThread@@YGPAVCWinThread@@P6AIPAX@Z0HIKPAU_SECURITY_ATTRIBUTES@@@Z ; AfxBeginThread(uint (*)(void *),void *,int,uint,ulong,_SECURITY_ATTRIBUTES *)

mov     eax, 1

wait

jmp     loc_51F405

看看谁发的消息(ID = 0x14EB or 5355)。

在 fn_msg_proc_sub_B07090 看了,只是消息处理。

消息是外部投递进来的。

一般投递消息使用postmessage, 特别是这种neg窗口的消息,咱自己写程序,也不可能用sendmessage.

查看postmessage的调用点,找到 (ID = 0x14EB or 5355)的消息投递点。

1

2

3

4

5

6

.idata:006F97B0                                         ; CODE XREF: sub_498BE0+A↑p

.idata:006F97B0                                         ; sub_4B4630+88↑p ...

.idata:006F97B4 ; BOOL (__stdcall *PostMessageA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)

.idata:006F97B4                 extrn PostMessageA:dword

.idata:006F97B4                                         ; CODE XREF: sub_498320+160↑p

.idata:006F97B4                                         ; sub_4AE410+249↑p ...

查看 PostMessageA 的所有调用。

随便去一个postmessage处,看看代码格式。

1

2

3

4

5

6

.text:0049846F                 push    eax             ; lParam

.text:00498470                 push    14DFh           ; wParam

.text:00498475                 push    111h            ; Msg // 这是消息ID

.text:0049847A                 mov     eax, hWnd

.text:0049847F                 push    eax             ; hWnd

.text:00498480                 call    ds:PostMessageA

先找一下文本 push 14EBh

不好找。

将IDA中的反汇编,存成要给.asm, 再来找.

在asm中查找 14EBh,好多都不是。

还得在IDA中找找PostMessageA, 找到一处,就看看上面的MSG ID 是不是 14EBh

这样找也不行啊,好多ID是用参数传进来的。并不是一个立即数。

找找settimer, ID = 0x26

找到一个包装过的设置定时器的函数fn_setimer_sub_4B4B20,在这个函数中的SetTimer处下断点等着。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

.text:004B4B20 fn_setimer_sub_4B4B20 proc near         ; CODE XREF: sub_4F5860+17D↓p

.text:004B4B20                                         ; sub_4F5860+19C↓p ...

.text:004B4B20

.text:004B4B20 nIDEvent= dword ptr  4

.text:004B4B20 uElapse= dword ptr  8

.text:004B4B20 lpTimerFunc= dword ptr  0Ch

.text:004B4B20

.text:004B4B20 mov     eax, [esp+lpTimerFunc]

.text:004B4B24 mov     edx, [esp+uElapse]

.text:004B4B28 mov     ecx, [ecx+20h]

.text:004B4B2B push    eax                             ; lpTimerFunc

.text:004B4B2C mov     eax, [esp+4+nIDEvent]

.text:004B4B30 push    edx                             ; uElapse

.text:004B4B31 push    eax                             ; nIDEvent

.text:004B4B32 push    ecx                             ; hWnd

.text:004B4B33 call    dword ptr ds:SetTimer // F2 here

.text:004B4B39 retn    0Ch

.text:004B4B39 fn_setimer_sub_4B4B20 endp

不好使

查找 push 26h 下面是settimer的,找到下面几处。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

loc_507C10:                             ; CODE XREF: sub_506E90+CBC↑j

                mov     eax, [esp+1E4h+var_1D0]

                push    eax

                call    esi ; GetDesktopWindow

                push    eax

                call    fn_show_dl_url_sub_53BEB0

                mov     eax, hWnd

                add     esp, 8

                cmp     eax, ebp

                jz      short loc_507C38

                push    ebp             ; lpTimerFunc

                push    36EE80h         ; uElapse

                push    26h ; '&'       ; nIDEvent

                push    eax             ; hWnd

                call    ds:SetTimer

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

loc_50AF20:                             ; CODE XREF: fn_show_neg_wnd_sub_50A1A0+CBC↑j

                mov     eax, [esp+1E4h+var_1D0]

                push    eax

                call    esi ; GetDesktopWindow

                push    eax

                call    fn_show_dl_url_sub_53BEB0

                mov     eax, hWnd

                add     esp, 8

                cmp     eax, ebp

                jz      short loc_50AF48

                push    ebp             ; lpTimerFunc

                push    36EE80h         ; uElapse

                push    26h ; '&'       ; nIDEvent

                push    eax             ; hWnd

                call    ds:SetTimer

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

; ---------------------------------------------------------------------------

 

loc_5105F3:                             ; CODE XREF: sub_50FC00+4F↑j

                                        ; DATA XREF: .text:jpt_50FC4F↓o

;   try {                               ; jumptable 0050FC4F case 38

                mov     [ebp+64h+var_68], 14h

                wait

                push    26h ; '&'       ; uIDEvent

                mov     edx, [esi+20h]

                push    edx             ; hWnd

                call    ds:KillTimer

                push    0               ; lParam

                push    14BFh           ; wParam

                push    111h            ; Msg

                mov     eax, [esi+20h]

                push    eax             ; hWnd

                call    ds:PostMessageA

                wait

;   } // starts at 5105F3

                mov     [ebp+64h+var_68], 0FFFFFFFFh

IDA中跳到一个地址或label,按 G 键,在编辑框中输入label名称或地址就行。

不好查,这些断点都不是很快能触发的。

非要从根上找到判断文件被修改的实现也不是不行,不值当,没那么多时间陪作者玩。
我们要的是解决问题(去掉neg弹窗)。
那只能先暴力一点点,将找到的起neg线程的地方nop掉。管他呢,将bug修复了再说。

找到的起neg线程的代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

loc_51D68F:             ; jumptable 00519AAA case 5355

; 0x14EB is 5355

push    0

push    0               ; unsigned int

push    0               ; StackSize

push    0               ; int

push    0               ; void *

push    offset fn_show_neg_wnd_sub_50A1A0 ; unsigned int (__cdecl *)(void *)

call    ?AfxBeginThread@@YGPAVCWinThread@@P6AIPAX@Z0HIKPAU_SECURITY_ATTRIBUTES@@@Z ; AfxBeginThread(uint (*)(void *),void *,int,uint,ulong,_SECURITY_ATTRIBUTES *)

mov     eax, 1

wait

jmp     loc_51F405

给这段代码打补丁,前9句都换成nop.
打补丁时,要注意堆栈平衡。否则打过补丁的程序跑起来,过了打补丁的地方就崩了。

打过补丁的代码如下:

保存工程

将原始文件复制一份,改名保存. e.g. test_org.exe

保存补丁

可以看到打补丁成功。

退出IDA, 单独直接运行修改过的同名程序。

开始跑起来,连续跑1天(24小时),看看会出啥问题不?

neg线程前面单步调试过,除了起neg窗口和开网页去官网下载页,没看到有啥其他功能。
按理说,只是去掉了neg线程的启动,应该没啥不良反应。

等着看疗效。

测试

  • 重新下载列表中的程序

启动了安装好的程序建立的快捷方式,程序跑起来了。

重新下载了一个下载好的文件,可以重新下载,非常好,没有不良反应。

  • 现在就等着就行了,看看会不会再出neg框。

前几天测试,刚装好,是1,2个小时就会出一次neg框。

这2天,是一天会出个几次neg框。弹窗节奏是越来越慢了,不知道作者是不是害怕了? 还是针对调试者做了特殊处理?(看到程序中有检测调试器的操作,逻辑没细看)

现在将程序直接跑起来(2022_0505_1600),下载都正常。准备跑12+个小时,看看还出neg窗口不?
现在直接将打过补丁的IDM运行起来了,已经过去了3个小时,期间也下载了新远程文件,功能正常。


现在已经过了24小时了(2022_0506_1717), IDM一直开着,期间下载了几次几百MB的远程文件,功能正常。

感觉是搞定了这个bug,先这样。

END

原版作者做了一些处理,用于隐藏neg窗口的启动流程。

不过用neg窗口这种东西,惹毛了用户,被盯上了,就难看了:) 还不如直接不给用。

如果给用,但是不断骚扰使用者,用户不是愤怒(谁要是老撩拨自己,肯定不爽啊)就是好奇啊。
用户有2种:

一种是觉得这软件真好用,离不开啊…,非要死皮赖脸的用,过了一段时间,被neg窗口整疯了,直接跪了,掏钱买原版。另外一种是喜欢DIY的用户,打死都没零钱买原版,这咋整啊?
有动手能力的用户会尝试去调试bug, 这是免不了的。调试个程序,谁还不会啊? 多大点事…
最后能不能将bug搞定,看实力也看运气,啥不会我现学行不? 只要bug是可以重现的,总有解决的那一天,调试者有的是时间和思路。

总的来说,只要有需求,调试者(逆向工程师)比作者(纯正向工程师)更有耐心。
作者要考虑的多,必有疏漏。这是一定的。不是有个成语"百密一疏"么?
调试者只是针对一个bug,可以撒着欢的调试。

补充 - 2022_0518_1602

现在已经用改过的IDM 6.40.11.2 很久了. 效果非常好, 没有副作用.
看来bug修正思路是正确的.

补充 - 2022_0530_1638

有的同学非要下载链接, 还不是一个人这样要求…
鄙人承诺: 此博客文章没有下载链接.
我们都不要做违法的事情, 这是底线啊.
IDM 6.40.11.2 的这个弹窗bug, 修正的思路和实现细节已经描述的很清楚. 仅供有兴趣的同学在DIY时参考.
只是抛砖引玉, 说不定能引发您想出更好的思路.
对DIY没兴趣的同学, 只能坐等网上大神们放出新的和谐包了. 请不要在此博客再留言要下载链接.

补充 - 2022_1021_2149

今天有同学留言, 问具体咋解决的.
看到这样的留言, 整的我好无语. 这文章不是将思路和实现细节都讲清楚了么? 言无不尽啊, 不知道再补充些什么才好.

如果看了这篇文章还不知道怎么用DIY的方法来解决IDM弹窗的bug, 那说明您需要补充一些逆向方面的知识.
基本这篇文章对您现阶段没用, 大家不在一个频道.

今天这么留言的同学, 后来告诉我, 已经找到第三方的工具(e.g. 火绒, 360), 将IDM弹窗拦截了, 不用自己来DIY.
这就对了么!

每个人遇到问题, 总是要找到适合自己现阶段的方法. 别人的解决方案仅供参考. 如果找到的资料对自己没用, 就继续找资料, 做实验.
不断折腾, 总有能正常使用的那一个高光时刻.

这个补充说明, 不仅仅针对这个具体bug, 其他事情也是一样的, 总是要自己不断折腾, 才能找到适合自己现阶段的方法. 这世界上, 现成的事情是很少的, 也有些事情是钱买不来的, 需要自己动手才有吃的


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。

您可能感兴趣的文章 :

原文链接 : https://blog.csdn.net/LostSpeed/article/details/124613351
相关文章
  • 秒杀系统设计的5个要点介绍
    秒杀系统涉及到的知识点 高并发,cache,锁机制 基于缓存架构redis,Memcached的先进先出队列。 稍微大一点的秒杀,肯定是分布式的集群的,并
  • IDM 6.40.11.2 弹窗的完美解决思路

    IDM 6.40.11.2 弹窗的完美解决思路
    IDM 6.40.11.2 弹窗的解决思路 前言 在IDM官方下载了IDM的30天试用版。 装好后,找了一个和谐工具。运行和谐工具后,看IDM关于那里,已经是全
  • ChatGPT会成为下一代搜索引擎之王吗?seo在哪里?

    ChatGPT会成为下一代搜索引擎之王吗?seo在哪里?
    ChatGPT 直接颠覆了 SEO行业,能直接为用户生成答案的 ChatGPT 可能很快就会取代谷歌成为下一代搜索引擎,再也没有什么提高网页排名,SEO 也
  • vscode终端输出中文乱码问题解决图文教程

    vscode终端输出中文乱码问题解决图文教程
    解决vscode终端输出中文乱码问题,强推方法二,少走几年弯路 解决网上终端chcp65001仍然无效,或者vscode由utf-8改为GBK仍然无效的问题,提供
  • ROS机器人底盘坐标像素变换操作方法

    ROS机器人底盘坐标像素变换操作方法
    对于ROS小车底盘地图数据需要知道的点 1.整幅地图处于第三象限 2.坐标值代表距离,单位米。 3.分辨率单位(米/像素) 因此通过地图坐标得
  • ROS  TF坐标变换基本概念及使用案例介绍

    ROS TF坐标变换基本概念及使用案例介绍
    TF(TransForm),就是坐标转换,包括了位置和姿态两个方面的变换,坐标变换是机器人学中的概念。 在机器人学中,无论一个机器人多么复杂,
  • 程序猿表白妹子的代码神器
    女生眼中的程序员,身上带着好多标签直男,宅,不懂浪漫,枯燥,但这是因为你还没有了解程序猿,程序猿也可以非常浪漫。 程序猿用代
  • Flutter Dart快速排序算法介绍
    在日常研发的过程中,我们无时无刻都在考虑自己开发的程序是否高效,一段好的程序执行离不开对算法的深刻认识和熟练掌握。接下来的
  • VSCode如何巧用正则表达式快速处理字符段

    VSCode如何巧用正则表达式快速处理字符段
    正则表达式 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为元字符)。 正则表达
  • s49 磁盘存储文件系统管理介绍

    s49 磁盘存储文件系统管理介绍
    第一部分 1、创建一个2G的文件系统 块大小为2048byte,预留1%可用空间,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/test目录,且
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计