3. HITCON CMT 2016
Introduction
Ransomware[1][2]
• DoS victims from accessing their system
• "claim" something has been kidnapped and tell
victims need to pay for retaining the kidnapee
• anonymity of the transaction is the most difficult
• cryptocurrency, voucher, Tor
• no one can guarantee the kidnapee will be back
after paid
3
5. HITCON CMT 2016
Background
Types of Ransomware
• misleading application[3][4]
• free vs. non-free
• e.g. performance optimizer, fake AV
• police ransomware
• fake local law enforcement
• crypto ransomware
5
6. HITCON CMT 2016
Background
History of Ransomware on OS X[5]
• July 2013, FBI ransomware[6][7]
• June 2014, FileCoder[8]
• Sep 2015, Gopher[9]
• Nov 2015, Mabouia[10]
• Feb 2016, GinX[11]
• Mar 2016, KeRanger[12] (see Appendix A)
6
7. HITCON CMT 2016
Related Works
• Toward Generic (Crypto) Ransomware Detection[5]
• monitoring file I/O events
• determining if a file is encrypted
• determining if a process is untrusted
• RansomWhere?[13]
➡sniffer mode limitation: still sacrificed a few files
7
8. HITCON CMT 2016
FèlDo
Overview
• an inline mode solution for detecting and preventing crypto
ransomware
• detection: correlating function calls
• crypto ransomware is relatively simple (at least for now)
• it is possible to detect them via observing function calling
sequence
• within a short time frame
• prevention: hooking APIs
• deferring unlink request
8
10. HITCON CMT 2016
FèlDo
Correlating Function Calls (2/2)
10
open_nocancel("/Users/tester/.CFUserTextEncoding0", 0x0, 0x1B6) = 6 0
open_nocancel("/Users/tester/.CFUserTextEncoding.encrypted0", 0x601, 0x1B6) = 7 0
close_nocancel(0x6) = 0 0
close_nocancel(0x7) = 0 0
unlink("/Users/tester/.CFUserTextEncoding0", 0x7FFF5FBFDE00, 0x154) = 0 0
If frequency of two-pair greater than
thresholdA, the corresponding
process is likely a crypto ransomware.
in-place vs. not-in-place encryption
11. HITCON CMT 2016
FèlDo
Hooking APIs
• acknowledged whenever a process request to unlink
• put the request into a deferred queue
• the queue purges in two criteria: space and time limit
• if queue length is greater than thresholdB
• if a request has deferred for thresholdC seconds
• satisfies remaining requests while the process
terminating
11
even non-existent
12. HITCON CMT 2016
Implementation
OS X
• userland solution
• supports from dynamic linker "dyld"
• DYLD_INSERT_LIBRARIES
• DYLD_FORCE_FLAT_NAMESPACE
• kernel extension solution
• replace entries of system call table
12
application
library
system call
kernel
userland solution
kext solution
13. HITCON CMT 2016
Simple Evaluation
13
unit
(second)
original userland solution kext solution
round 1 round 2 round 3 average round 1 round 2 round 3 average round 1 round 2 round 3 average
test1.sh 49.66 50.97 50.17 50.27 136.80 140.66 137.13 138.20 51.08 50.27 51.03 50.79
test2.sh 34.67 33.83 32.78 33.76 107.30 105.41 107.00 106.57 34.08 34.88 33.15 34.04
test3.sh 32.73 31.37 32.11 32.07 142.27 142.25 144.37 142.96 32.52 32.35 31.92 32.26
$ cat test1.sh
for i in $(seq 1 10000)
do
touch $i
rm $i
done
$ cat test2.sh
for i in $(seq 1 4)
do
(
for k in $(seq 1 3000)
do
touch ${i}_${k}
rm ${i}_${k}
done
) &
done
wait
$ cat test3.sh
cd yara
sh build.sh >/dev/null 2>&1
userland solution: too many performance penalties (2x~4x slower)
kext solution: almost transparent
14. HITCON CMT 2016
Summary
• ransomware is variable
• crypto ransomware is just one kind of them
• IMHO, a product for crypto ransomware should be
• kernel mode and leverage existing mechanisms,
e.g. KAuth
• multiple detection criteria
• white listing
14
19. HITCON CMT 2016
OSX.KeRanger (3/14)
Drop File
19
fork, exec, wait
copy General.rtf to kernel_service
There will be a process named "kernel_service".
22. HITCON CMT 2016
OSX.KeRanger (6/14)
Daemonlize and Wait
22
fork, setsid, chdir
sleep 300 seconds until 3 days has elapsed
its parent "Transmission" can keep going
done flag
25. HITCON CMT 2016
OSX.KeRanger (9/14)
C2 Communication (2/2)
25
• server will respond 2 lines (base64-encoded)
• 1st line
• RSA public key
• 2nd line
• ransom statement
32. HITCON CMT 2016
Fake C2 Server (2/3)
Generate Private and Public Key
32
# openssl genrsa -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
....................................................+++
...............................................+++
e is 65537 (0x10001)
# openssl rsa -in private.pem -pubout -outform PEM -out public.pem
writing RSA key
# printf "x00" >> public.pem
# base64 public.pem
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE3eGd
TWW9MVWljNWxadnBiaXZ3NApXZzJFNUJpdk4vcW9vUmVTUEl4Z3lvYzZNMGdXR01pUUZmdVlMQjVxS2hXR2hmQjViWVh5K2hrak
hYWC84Z2l1CmJCa0szYU9RdmdlUmtKemR4NVFvbG5XNWxqRzVFUU9hZ0pCRk1RSHFIaHFqbXJDY0dFTis3c0N4YngrMGdYUGMKV
URJUEE1VXhLdjlneGFhMHQweHVoeWovUVhNMjF3V25mUkVxclU5MmdMSHIwdEpqR0E5Y2FPZ1cxbXVZM2U4UwpjQno5K3NJaWxv
RVBNSVNqa3N3dGR5OE96Q2FQYS9LU1J2T1lleXhsVGlCNDJrbEV2WmpyVkJ2ODZza09uQ0xNCkdSaWpCRkNyVnkwVVNKTDh4WHR
RMEJJNjZWTzB1b21oOXV4cC9Na1pLWk4yNmhraDNUSEVXL2xUdnBnYXlPSW8KbFFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS
0tLS0tCgA=
un-usual practice
33. HITCON CMT 2016
Fake C2 Server (3/3)
Dummy Web Application
33
# cat dummy.py
from flask import Flask
from flask import request
web_app = Flask('dummy')
@web_app.route('/osx/ping', methods=['GET'])
def dummy():
r = list()
r.append('LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ
0FRRUE3eGdTWW9MVWljNWxadnBiaXZ3NApXZzJFNUJpdk4vcW9vUmVTUEl4Z3lvYzZNMGdXR01pUUZmdVlMQjVxS2hXR2hmQjVi
WVh5K2hrakhYWC84Z2l1CmJCa0szYU9RdmdlUmtKemR4NVFvbG5XNWxqRzVFUU9hZ0pCRk1RSHFIaHFqbXJDY0dFTis3c0N4Yng
rMGdYUGMKVURJUEE1VXhLdjlneGFhMHQweHVoeWovUVhNMjF3V25mUkVxclU5MmdMSHIwdEpqR0E5Y2FPZ1cxbXVZM2U4UwpjQn
o5K3NJaWxvRVBNSVNqa3N3dGR5OE96Q2FQYS9LU1J2T1lleXhsVGlCNDJrbEV2WmpyVkJ2ODZza09uQ0xNCkdSaWpCRkNyVnkwV
VNKTDh4WHRRMEJJNjZWTzB1b21oOXV4cC9Na1pLWk4yNmhraDNUSEVXL2xUdnBnYXlPSW8KbFFJREFRQUIKLS0tLS1FTkQgUFVC
TElDIEtFWS0tLS0tCgA=')
r.append('c29tZSByYW5zb20gc3RhdGVtZW50Li4uCg==')
return 'n'.join(r)
web_app.run(host='0.0.0.0', port=80)
indented; don't be confused
34. HITCON CMT 2016
Experiment (1/2)
Cheat the Malware
34
$ cp General.rtf AAAA
$ ./AAAA
$ killall AAAA
$ ls -a Library/.kernel*
Library/.kernel_pid
Library/.kernel_time
$ echo 0 > Library/.kernel_time
will be unlinked
will be detached
cheat the malware 3+ days has elapsed
36. HITCON CMT 2016
Rescue (1/5)
Encrypted File Format
36
XXX.encrypted
len
{seed}pub
IV
cipher text
HMAC
4 bytes
256 bytes
16 bytes
32 bytes
(determined by len)
37. HITCON CMT 2016
Rescue (2/5)
Get Secret Key
37
IV16 bytes
key
md
seed
32 bytes 32 bytes
run over 8 times
message digest
38. HITCON CMT 2016
Rescue (3/5)
Decryption
38
IV
AES
cipher text
key
plain text
16 bytes 32 bytes
32 bytes
32 bytes
IV will be replaced after the first round
39. HITCON CMT 2016
Rescue (4/5)
Trim File Until Matches HMAC
39
plain text
may exist some (garbage) paddings; at most 31 bytes
AES
cipher text
40. HITCON CMT 2016
Rescue (5/5)
Decryption Tool
40
$ cat decrypt_file.c
[snip]
if (!get_seed(argv[1], encrypted_seed, encrypted_seed_len, seed, &seed_len)) {
ERR("failed to get_seed");
goto leave;
}
dump_binary("seed", seed, seed_len);
if (!get_key(iv, seed, key)) {
ERR("failed to get_key");
goto leave;
}
dump_binary("key", key, 32);
if (!decrypt_file(encrypted_seed_len, iv, key, fin, fout)) {
ERR("failed to decrypt_file");
goto leave;
}
DBG("decrypt_file success");
if (!trim_file(key, hmac, fout)) {
ERR("failed to trim_file");
goto leave;
}
DBG("trim_file success");
[snip]