Clipboard Hijacker Detection
Can we statically detect clipboard hijacking
Overview
In general clipboard hijackers are used to monitor clipboard activity on a target host, and swap valuable data like BTC addresses. We would like a generic static method for detecting this behaviour.
Samples
-
8d7f0e6b6877bdfb9f4531afafd0451f7d17f0ac24e2f2427e9b4ecc5452b9f0
Malshare
import re
def get_unicode_strings(buf, n=4):
ASCII_BYTE = b' !\"#\$%&\'\(\)\*\+,-\./0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\}\\\~\t'
if type(buf) == str:
buf = buf.encode('utf-8')
reg = b'((?:[%s]\x00){%d,})' % (ASCII_BYTE, n)
uni_re = re.compile(reg)
out = []
for match in uni_re.finditer(buf):
try:
out.append(match.group().decode("utf-16"))
except UnicodeDecodeError:
pass
return out
coin_eggs = {
"btc": "[13][a-km-zA-HJ-NP-Z1-9]{25,34}",
"bch": "((bitcoincash|bchreg|bchtest):)?(q|p)[a-z0-9]{41}",
"eth": "0x[a-fA-F0-9]{40}",
"ltc": "[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}",
"doge": "D{1}[5-9A-HJ-NP-U]{1}[1-9A-HJ-NP-Za-km-z]{32}",
"dash": "X[1-9A-HJ-NP-Za-km-z]{33}",
"xmr": "4[0-9AB][1-9A-HJ-NP-Za-km-z]{93}",
"neo": "A[0-9a-zA-Z]{33}",
"xrp": "r[0-9a-zA-Z]{33}"}
coin_eggs2 = {
"bitcoin": r"[13][a-km-zA-HJ-NP-Z1-9]{25,34}",
"bech32": r"bc(0([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59})|1[ac-hj-np-z02-9]{8,87})",
"bitcoin_cash": r"[13][a-km-zA-HJ-NP-Z1-9]{33}",
"dash": r"X[1-9A-HJ-NP-Za-km-z]{33}",
"ethereum": r"0x[a-fA-F0-9]{40}$",
"litecoin": r"[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}",
"monero": r"4[0-9AB][1-9A-HJ-NP-Za-km-z]{93}$"}
file_data = open('/tmp/8d7f0e6b6877bdfb9f4531afafd0451f7d17f0ac24e2f2427e9b4ecc5452b9f0.bin','rb').read()
u_strings = get_unicode_strings(file_data)
for u_string in u_strings:
for coin_name in coin_eggs.keys():
coin_egg = coin_eggs[coin_name]
m = re.match(coin_egg, u_string)
if m:
print(f"{coin_name}: {m.group()}")
coin_eggs2 = {
"bitcoin": r"[13][a-km-zA-HJ-NP-Z1-9]{25,34}",
"bech32": r"bc(0([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59})|1[ac-hj-np-z02-9]{8,87})",
"bitcoin_cash": r"[13][a-km-zA-HJ-NP-Z1-9]{33}",
"dash": r"X[1-9A-HJ-NP-Za-km-z]{33}",
"ethereum": r"0x[a-fA-F0-9]{40}$",
"litecoin": r"[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}",
"monero": r"4[0-9AB][1-9A-HJ-NP-Za-km-z]{93}$"}
print("\nTry 2\n")
for u_string in u_strings:
for coin_name in coin_eggs2.keys():
coin_egg = coin_eggs2[coin_name]
m = re.match(coin_egg, u_string)
if m:
print(f"{coin_name}: {m.group()}")
Yara Rule
First we can take a look at how they parse out the coin addresses from the clipboard.
General Check
text:004014B1 6A 30 push 30h ; '0' ; wMatch
.text:004014B3 56 push esi ; pszStart
.text:004014B4 FF 15 18 40 40 00 call StrChrW
.text:004014BA 85 C0 test eax, eax
.text:004014BC 0F 85 83 00 00 00 jnz loc_401545
.text:004014C2 6A 4F push 4Fh ; 'O' ; wMatch
.text:004014C4 56 push esi ; pszStart
.text:004014C5 FF 15 18 40 40 00 call StrChrW
.text:004014CB 85 C0 test eax, eax
.text:004014CD 75 76 jnz short loc_401545
.text:004014CF 6A 49 push 49h ; 'I' ; wMatch
.text:004014D1 56 push esi ; pszStart
.text:004014D2 FF 15 18 40 40 00 call StrChrW
.text:004014D8 85 C0 test eax, eax
.text:004014DA 75 69 jnz short loc_401545
BTC Check
cmp eax, 2Ah ; '*'
.text:004015C3 75 5B jnz short loc_401620
.text:004015C5 66 39 1E cmp [esi], bx
.text:004015C8 75 56 jnz short loc_401620
.text:004015CA 66 39 4E 02 cmp [esi+2], cx
.text:004015CE 75 50 jnz short loc_401620
.text:004015D0 6A 31 push 31h ; '1'
.text:004015D2 58 pop eax
.text:004015D3 66 39 46 04 cmp [esi+4], ax
.text:004015D7 75 47 jnz short loc_401620
.text:004015D9 6A 4F push 4Fh ; 'O' ; wMatch
.text:004015DB 8D 5E 06 lea ebx, [esi+6]
.text:004015DE 53 push ebx ; pszStart
.text:004015DF FF 15 18 40 40 00 call StrChrW
.text:004015E5 85 C0 test eax, eax
.text:004015E7 75 34 jnz short loc_40161D
.text:004015E9 6A 49 push 49h ; 'I' ; wMatch
.text:004015EB 53 push ebx ; pszStart
.text:004015EC FF 15 18 40 40 00 call StrChrW
.text:004015F2 85 C0 test eax, eax
.text:004015F4 75 27 jnz short loc_40161D
rule $ btc_find = {6A 31 [4-16] 75 ?? 6A 4F [4-16] 75 ?? 6A 49}
rule clipboard_hijack {
meta:
description = "Identifies clipboard hijacking"
strings:
$btc_find = {6A 31 [4-16] 75 ?? 6A 4F [4-16] 75 ?? 6A 49}
$coin_find = {6A 30 [4-16] 75 ?? 6A 4F [4-16] 75 ?? 6A 49}
$s1 = "GetClipboardData" ascii wide
$s2 = "SetClipboardData" ascii wide
condition:
all of them
}