首页
社区
课程
招聘
用OLLY进行真正的Debug
发表于: 2004-8-31 16:02 9291

用OLLY进行真正的Debug

RoBa 活跃值
16
2004-8-31 16:02
9291
想要写个木马玩玩,什么功能也没有,就是监视键盘记录并发送到指定邮箱里。上网去找发邮件的例子,试试都不行,现在的邮箱都采取的验证的方式,以前的方法不能用了。正在无计可施时突然发现老罗的网站上一篇正是讲这个的(http://www.luocong.com/articles/show_article.asp?Article_ID=21),一试之下大喜,对老罗的崇拜之情如滔滔江水。。。

可是没多久问题又来了,程序只有在连入网络发信才成功,当断线时发信会“非法操作”。(我用的98,不知别的系统怎样)这可不行,明摆着暴露自己嘛。可是把代码分析了半天也不知道错在哪儿。下面是部分代码(不好意思不能保持完整了):
.if eax == IDC_BUTTON_SEND
;以下是初始化 winsock :
	invoke WSAStartup, 101h, addr wsadata
	.if eax != NULL
		invoke MessageBox, hWnd, addr szErrNoDll, addr szCaption, MB_OK or MB_ICONHAND
	.else
		invoke socket, AF_INET, SOCK_STREAM, 0
		.if eax == INVALID_SOCKET
		invoke MessageBox, hWnd, addr szErrSocket, addr szCaption, MB_OK or MB_ICONHAND
		.else
			mov hSocket, eax
			mov sin.sin_family, AF_INET
			invoke htons, 25
			mov sin.sin_port, ax
			invoke GetDlgItemText, hWnd, IDC_EDIT_SMTPSERVER, addr szSmtpServer, 255
			invoke gethostbyname, addr szSmtpServer
			mov eax, [eax + 12]
			mov eax, [eax]
			mov eax, [eax]
			mov sin.sin_addr, eax
			invoke connect, hSocket, addr sin, sizeof sin
			.if eax < 0
			invoke MessageBox, hWnd, addr szErrConnect, addr szCaption, MB_OK or MB_ICONHAND
			.else
			;下面是正常的发送过程了,省略
			.endif
		.endif
	.endif
.endif

看上去没有问题嘛,把所有出错的地方都考虑进去了,为什么还会非法操作呢?我又用VC++用MFC写了一个,用封装好的CSocket类。源代码:
	CSocket mySocket;
	mySocket.Create(0,SOCK_STREAM);
	if (!mySocket.Connect("smtp.163.com",25)) {
		MessageBox("Cannot Connect!");
		return;
	}
	strcpy(string,"EHLO smtp.163.com\r\n");
	mySocket.Send(string,strlen(string));

这个没有问题,如果没有连网就会弹出"Cannot Connet!"。MFC是怎么做的呢,咱们把它反汇编看看:
00401504   . 6A 19          PUSH 19
00401506   . 68 E0314000    PUSH EMAIL2.004031E0                     ;  ASCII "smtp.163.com"
0040150B   . 8D4C24 10      LEA ECX,DWORD PTR SS:[ESP+10]
0040150F   . E8 48060000    CALL <JMP.&MFC42.#2029>                  ;这个CALL是关键,进入
00401514   . 85C0           TEST EAX,EAX
00401516   . 75 39          JNZ SHORT EMAIL2.00401551                ;如果没有连网就不会跳
00401518   . 50             PUSH EAX
00401519   . 50             PUSH EAX
0040151A   . 68 D0314000    PUSH EMAIL2.004031D0                     ;  ASCII "Cannot Connect!"
0040151F   . 8BCD           MOV ECX,EBP
00401521   . E8 30060000    CALL <JMP.&MFC42.#4224>

跟进CALL(对应上面语句中的mySocket.Connect):

6BC56684 > 55               PUSH EBP
6BC56685   8BEC             MOV EBP,ESP
6BC56687   83EC 10          SUB ESP,10
6BC5668A   56               PUSH ESI
6BC5668B   6A 10            PUSH 10
6BC5668D   8D45 F0          LEA EAX,DWORD PTR SS:[EBP-10]
6BC56690   6A 00            PUSH 0
6BC56692   8BF1             MOV ESI,ECX
6BC56694   50               PUSH EAX
6BC56695   E8 AEB0FEFF      CALL <JMP.&MSVCRT.memset>
6BC5669A   83C4 0C          ADD ESP,0C
6BC5669D   66:C745 F0 0200  MOV WORD PTR SS:[EBP-10],2
6BC566A3   FF75 08          PUSH DWORD PTR SS:[EBP+8]
6BC566A6   E8 40000000      CALL MFC42.6BC566EB                      ; JMP to WSOCK32.inet_addr
6BC566AB   83F8 FF          CMP EAX,-1
6BC566AE   8945 F4          MOV DWORD PTR SS:[EBP-C],EAX
6BC566B1   75 1A            JNZ SHORT MFC42.6BC566CD
6BC566B3   FF75 08          PUSH DWORD PTR SS:[EBP+8]
6BC566B6   E8 42000000      CALL MFC42.6BC566FD                      ; JMP to WSOCK32.gethostbyname
6BC566BB   85C0             TEST EAX,EAX                             ; 找到了,关键就是这里
6BC566BD   0F84 799C0700    JE MFC42.6BCD033C                        ; 如果失败就跳走了
6BC566C3   8B40 0C          MOV EAX,DWORD PTR DS:[EAX+C]
6BC566C6   8B00             MOV EAX,DWORD PTR DS:[EAX]
6BC566C8   8B00             MOV EAX,DWORD PTR DS:[EAX]
6BC566CA   8945 F4          MOV DWORD PTR SS:[EBP-C],EAX
6BC566CD   FF75 0C          PUSH DWORD PTR SS:[EBP+C]
6BC566D0   E8 8BFFFFFF      CALL MFC42.6BC56660                      ; JMP to WSOCK32.htons

前面都没有问题,过6BC566B6一句CALL gethostbyname的时候发现返回值EAX为0,然后就跳走了。而老罗的代码用OLLY跟一下是这样的:
0040111E  |. 68 C6324000    PUSH SMTP.004032C6                       ; /pWSAData = SMTP.004032C6
00401123  |. 68 01010000    PUSH 101                                 ; |RequestedVersion = 101 (1.1.)
00401128  |. E8 4F070000    CALL <JMP.&WSOCK32.#115>                 ; \WSAStartup
0040112D  |. 0BC0           OR EAX,EAX
0040112F  |. 74 19          JE SHORT SMTP.0040114A
00401131  |. 6A 10          PUSH 10                                  ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401133  |. 68 0A304000    PUSH SMTP.0040300A                       ; |Title = "ESmtp demo by LC, 2002-10-12"
00401138  |. 68 27304000    PUSH SMTP.00403027                       ; |Text = "装载winsock.dll时出错!"
0040113D  |. FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
00401140  |. E8 19070000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
00401145  |. E9 1C060000    JMP SMTP.00401766
0040114A  |> 6A 00          PUSH 0                                   ; /Protocol = IPPROTO_IP
0040114C  |. 6A 01          PUSH 1                                   ; |Type = SOCK_STREAM
0040114E  |. 6A 02          PUSH 2                                   ; |Family = AF_INET
00401150  |. E8 51070000    CALL <JMP.&WSOCK32.#23>                  ; \socket
00401155  |. 83F8 FF        CMP EAX,-1
00401158  |. 75 19          JNZ SHORT SMTP.00401173                  ;这里并没有出错而是跳过去了
0040115A  |. 6A 10          PUSH 10                                  ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0040115C  |. 68 0A304000    PUSH SMTP.0040300A                       ; |Title = "ESmtp demo by LC, 2002-10-12"
00401161  |. 68 3F304000    PUSH SMTP.0040303F                       ; |Text = "建立socket时出错!"
00401166  |. FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
00401169  |. E8 F0060000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
0040116E  |. E9 77050000    JMP SMTP.004016EA
00401173  |> A3 FC344000    MOV DWORD PTR DS:[4034FC],EAX
00401178  |. 66:C705 543440>MOV WORD PTR DS:[403454],2
00401181  |. 6A 19          PUSH 19                                  ; /HostSshort = 19
00401183  |. E8 0C070000    CALL <JMP.&WSOCK32.#9>                   ; \htons
00401188  |. 66:A3 56344000 MOV WORD PTR DS:[403456],AX
0040118E  |. 68 FF000000    PUSH 0FF                                 ; /Count = FF (255.)
00401193  |. 68 00354000    PUSH SMTP.00403500                       ; |Buffer = SMTP.00403500
00401198  |. 68 B90B0000    PUSH 0BB9                                ; |ControlID = BB9 (3001.)
0040119D  |. FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
004011A0  |. E8 AD060000    CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
004011A5  |. 68 00354000    PUSH SMTP.00403500                       ; /Name = ""
004011AA  |. E8 DF060000    CALL <JMP.&WSOCK32.#52>                  ; \gethostbyname
004011AF  |. 8B40 0C        MOV EAX,DWORD PTR DS:[EAX+C]             ; EAX=0到这里会怎么样呢?:D
004011B2  |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
004011B4  |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
004011B6  |. A3 58344000    MOV DWORD PTR DS:[403458],EAX
004011BB  |. 6A 10          PUSH 10                                  ; /AddrLen = 10 (16.)
004011BD  |. 68 54344000    PUSH SMTP.00403454                       ; |pSockAddr = SMTP.00403454
004011C2  |. FF35 FC344000  PUSH DWORD PTR DS:[4034FC]               ; |Socket = 0
004011C8  |. E8 BB060000    CALL <JMP.&WSOCK32.#4>                   ; \connect
004011CD  |. 83F8 00        CMP EAX,0
004011D0  |. 73 19          JNB SHORT SMTP.004011EB
004011D2  |. 6A 10          PUSH 10                                  ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004011D4  |. 68 0A304000    PUSH SMTP.0040300A                       ; |Title = "ESmtp demo by LC, 2002-10-12"
004011D9  |. 68 52304000    PUSH SMTP.00403052                       ; |Text = "进行连接时出错!"
004011DE  |. FF75 08        PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
004011E1  |. E8 78060000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA

跟一下发现:在我们认为会出错的401150 这个CALL返回了正确的值,所以那个“建立Socket时出错”并不会跳出,而到4011AA这个CALL gethostbyname同样会返回0,因为没有进行处理接着进行MOV EAX,[EAX+C],想读DS:[0C]当然要死得很难看了:D

问题找到了,解决起来就容易多了,像MFC里一样在CALL gethostbyname后面加个判断就可以确保万无一失了(跟着M$没错)

高手肯定觉得这没什么了不起,但对于我来说,调试器真正用来给程序除错还是开天辟地头一遭,兴奋中。。。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (13)
雪    币: 319
活跃值: (1086)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
好贴。。。
又见好帖。。。
又见不是一般的好贴。。。
好贴不是别的。。。
好贴就是好贴。。。
好是好贴的好。。。
贴是好贴的帖。。。
好贴不是别的。。。
好贴就是好贴。。。
2004-8-31 18:00
0
雪    币: 97697
活跃值: (200829)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
支持!
2004-8-31 18:04
0
雪    币: 14
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
看看,也只能看看啦:D
2004-8-31 22:24
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
太强了,用汇编写木马
2004-8-31 22:48
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
老  罗在网上的说,  其实他是没有处理返回直的。。。
2004-9-1 06:55
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
呵呵,我用Ollydbg && IDA 找出并解决Intel编译器里的一个bug

直接面对汇编还是很惬意的
2004-9-2 00:00
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
强烈同意!
直接面对汇编感觉真好!
尤其是对Delphi这样的RAD,平时做数据库应用,真是很难有机会接触到ASM,大学里玩的差不多都忘记了。。。
最近在做简繁转换,呵呵,原来是做成COM的,而且基于GB2312与Big5,给他修改成了GBK与Big5。
可是还是有些字符转不过来。。。最后才发现原来是使用oleVariant的原因。。。
呵呵,用ASM跟踪下去,  才发现。。。
2004-9-2 00:10
0
雪    币:
能力值: (RANK: )
在线值:
发帖
回帖
粉丝
9
我觉得我拆程序比写程序强
写起来太累了
想来程序员写出个软件还真不容易啊
2004-9-2 10:11
0
雪    币: 261
活跃值: (230)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
:D 写是很多人创造
   拆是一个人比较

“”调试器真正用来给程序除错还是开天辟地头一遭,兴奋中。。。“”
好羡慕:p
2004-9-2 12:06
0
雪    币: 211
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
佩服ing。。。。。。
2004-9-2 14:16
0
雪    币: 212
活跃值: (70)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
........好厉害呀,
2004-9-2 20:19
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
WYC
13
佩服.佩服
2004-9-2 22:02
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
14
折东西总比盖东西省劲
2004-9-5 20:51
0
游客
登录 | 注册 方可回帖
返回
//