BlackPOS or Something New – Tracking Point of Sale Malware

June 6, 2015
Jeremy Humble
Nick Hoffman

Tracking Point of Sale malware and determining if the malware from the Home Depot Cyber Attack was different than what was used on Target

Using Intelligent Analysis and Adaptive Defense, all of us at CBTS Advanced Cyber Security want to learn from past attacks in order to better defend our customers from future attacks. Many times this involves finding new and novel ways to track malware, even point of sale malware. To this end, we became very interested when TrendMicro reported on a new variant of BlackPOS, which we will call MEMLOG.A for the sake of this post. In the blog post they are correlating this to the malware used to target Home Depot in the latest hack.

While it’s sensational to say that the same malware was used to target both Home Depot and Target, this is not looking like the case. There are already some entries coming out from other reverse engineers on this subject and this is not looking like BlackPOS at all.

Tracking Point of Sale Malware

In the blog post, TrendMicro alludes to the custom algorithm being used inside MEMLOG.A to validate and process CC information. “Based on our analysis, this PoS malware uses a new custom search routine to check the RAM for Track data. These custom search routines have replaced the regex search in newer PoS malware.” No other information is provided. On seeing this, we thought that perhaps these algorithms could be used as a way to track and identify Point of Sale malware. The MEMLOG.A sample that TrendMicro wrote up would be a good experiment to find out how similar these algorithms are across all Point of Sale malware.

Point of Sale malware often uses the same technique to find credit card numbers on the victim machine. The malware will scrape memory and then search for valid numbers. Regex is often used to find the numbers and then they are passed to a validation algorithm, in almost all cases this is Luhn’s algorithm. Normally, search for an implementation of Luhn’s algorithm on a Point of Sale machine will identify malware. In this case, when a custom algorithm is used, this is somewhat rare case, and interesting to anyone chasing POS malware. That said, by implementing a new and unique algorithm, the malware actually becomes easier to detect because nothing else uses that algorithm.

Detecting Point of Sale Malware

In the case of the MEMLOG.A malware that TrendMicro wrote up, the algorithms can be easily abstracted into yara rules to flag anytime the suspect algorithms exist inside a set of code. Even better, these rules will flag on other samples using the same algorithm. By implementing these rules, defenders can detect not just this version of the malware, but any version that uses this algorithm to find Track data in RAM. This will essentially force the attacker to rewrite their code or face detection.

rule Production_POS_CC_Algorithm
{
meta:
author = “Nick Hoffman – CBTS – ACS”
description = “Finds CC validation routines”
strings:
//00401224 |> /48 /DEC EAX
//00401225 |. |0FBE0C06 |MOVSX ECX,BYTE PTR DS:[ESI+EAX]
//00401229 |. |83E9 30 |SUB ECX,30
//0040122C |. |85FF |TEST EDI,EDI
//0040122E |. |75 04 |JNZ SHORT b579c886.00401234
//00401230 |. |8B4C8D D4 |MOV ECX,DWORD PTR SS:[EBP+ECX*4-2C]
//00401234 |> |03D9 |ADD EBX,ECX
//00401236 |. |33C9 |XOR ECX,ECX
//00401238 |. |85FF |TEST EDI,EDI
//0040123A |. |0F94C1 |SETE CL
//0040123D |. |8BF9 |MOV EDI,ECX
//0040123F |> |85C0 TEST EAX,EAX
//00401241 |.^\75 E1 \JNZ SHORT b579c886.00401224
$a = {480FBE0C0683E93085FF75 048B4C8DD403D933C985FF0F94C18BF985C075 E1 }
//004011DC |. 895D D4 MOV [LOCAL.11],EBX
//004011DF |. C745 D8 02000000 MOV [LOCAL.10],2
//004011E6 |. C745 DC 04000000 MOV [LOCAL.9],4
//004011ED |. C745 E0 06000000 MOV [LOCAL.8],6
//004011F4 |. C745 E4 08000000 MOV [LOCAL.7],8
//004011FB |. 8945 E8 MOV [LOCAL.6],EAX
//004011FE |. C745 EC 03000000 MOV [LOCAL.5],3
//00401205 |. C745 F0 05000000 MOV [LOCAL.4],5
//0040120C |. C745 F4 07000000 MOV [LOCAL.3],7
//00401213 |. C745 F8 09000000 MOV [LOCAL.2],9
$loadevenodd = {895D ?? C745 ?? 02000000 C745 ?? 04000000 C745 ?? 06000000 C745 ?? 08000000 8945 ?? C745 ?? 03000000 C745 ?? 05000000 C745 ?? 07000000 C745 ?? 09000000}
//.text:0040136E ; 22: if ( v4 )
//.text:0040136E 83 7D E0 00 cmp [ebp+var_20],
//.text:00401372 74 1F jz short loc_401393
//.text:00401374 ; 24: v6 *= 2;
//.text:00401374 8B 45 F8 mov eax, [ebp+var_8]
//.text:00401377 D1 E0 shl eax, 1
//.text:00401379 89 45 F8 mov [ebp+var_8], eax
//.text:0040137C ; 25: if ( (signed int)v6 > 9 )
//.text:0040137C 83 7D F8 09 cmp [ebp+var_8], 9
//.text:00401380 7E 11 jle short loc_401393
//.text:00401382 ; 26: v6 = (signed int)v6 % 10+ 1;
//.text:00401382 8B 45 F8 mov eax, [ebp+var_8]
//.text:00401385 99 cdq
//.text:00401386 B9 0A 00 00 00 mov ecx, 0Ah
//.text:0040138B F7 F9 idiv ecx
//.text:0040138D 83 C2 01 add edx, 1
//.text:00401390 89 55 F8 mov [ebp+var_8], edx
//.text:00401393 ; 28: v4 = v4 == 0;
//.text:00401393
//.text:00401393 loc_401393: CODE XREF: //.text:00401393 sub_4012D0+B0j
//.text:00401393 33 C0 xor eax, eax
//.text:00401395 83 7D E0 00 cmp [ebp+var_20], 0
//.text:00401399 0F 94 C0 setz al
//.text:0040139C 89 45 E0 mov [ebp+var_20], eax
//.text:0040139F ; 29: v3 += v6;
//.text:0040139F 8B 45 D4 mov eax, [ebp+var_2C]
//.text:004013A2 03 45 F8 add eax, [ebp+var_8]
//.text:004013A5 89 45 D4 mov [ebp+var_2C], eax
//.text:004013A8 EB 8C jmp short loc_401336
//.text:004013AA ; 31: result = v3 % 10 == 0;
//.text:004013AA
//.text:004013AA loc_4013AA: ; //.text:004013AA 8B 45 D4 mov eax, [ebp+var_2C]
//.text:004013AD 99 cdq
//.text:004013AE B9 0A 00 00 00 mov ecx, 10
//.text:004013B3 F7 F9 idiv ecx
//.text:004013B5 F7 DA neg edx
//.text:004013B7 1B D2 sbb edx, edx
//.text:004013B9 42 inc edx
//.text:004013BA 8B C2 mov eax, edx
//.text:004013BC ; 42: return result;
$blackpos = {83 7D E0 00 74 1F 8B 45 F8 D1 E0 89 45 F8 83 7D F8 09 7E 11 8B 45 F8 99 B9 0A 00 00 00 F7 F9 83 C2 01 89 55 F8 33 C0 83 7D E0 00 0F 94 C0 89 45 E0 8B 45 D4 03 45 F8 89 45 D4 EB 8C 8B 45 D4 99 B9 0A 00 00 00 F7 F9 F7 DA 1B D2 42 8B C2}
condition:
any of them
}

Comparing the Algorithms

Now that we know how to detect this new malware, let’s look at how it differs from past Point of Sale malware samples. In many cases Point of Sale malware has used a variant of Luhn’s algorithm. Understanding the different ways that this algorithm is implemented can help us differentiate between families of malware. Taking a look at a classic Luhn’s would yield the following code (in C++)

int confirm( const char *id)
{
bool is_odd_dgt = true;
int s = 0;
const char *cp;

for(cp=id; *cp; cp++);
while(cp > id) {
–cp;
int k = toInt(*cp);
if (is_odd_dgt) {
s += k;
}
else {
s += (k!=9)? (2*k)%9 : 9;
}
is_odd_dgt = !is_odd_dgt;
}
return 0 == s%10;
}

Now let’s compare this to the MEMLOG.A malware. For MEMLOG.A the following function stands out.

BlackPOS POS Malware

In classic Luhn’s implementation logic is used to keep track of odd and even numbers. In the MEMLOG.A implementation a lookup table is used to track odd and even numbers. This is a stylistic difference that is significant in determining the origin of each piece of malware.

Translating the MEMLOG.A implementation into pseudo-code will show the following

v1 = 0;
v6 = 0;
v7 = 2;
v8 = 4;
v9 = 6;
v10 = 8;
v11 = 1;
v12 = 3;
v13 = 5;
v14 = 7;
v15 = 9;
v2 = 1;
v3 = strlen(a1);
while ( v3 ) {
–v3;
v4 = a1[v3] – 48;
if ( !v2 )
v4 = *(&v6; + v4);
v1 += v4;
v2 = v2 == 0;
}
return v1 % 10 == 0;
}

Comparing the MEMLOG.A pseudo-code to pseudo-code from the BlackPOS samples found in Target, shows us that these are two very different implementations.

int __cdecl sub_4012D0(char *a1)
{
int result; // eax@2
char v2; // [sp+Ch] [bp-F0h]@1
int v3; // [sp+D0h] [bp-2Ch]@6
int v4; // [sp+DCh] [bp-20h]@6
size_t i; // [sp+E8h] [bp-14h]@6
size_t v6; // [sp+F4h] [bp-8h]@3
memset(&v2;, 0xCCu, 0xF0u);
if ( a1 )
{
v6 = strlen(a1);
if ( (signed int)v6 >= 13 && (signed int)v6 <= 19 )
{
v4 = 0;
v3 = 0;
for ( i = v6 – 1; (signed int)i > -1; –i )
{
if ( !isdigit(a1[i]) )
return 0;
v6 = a1[i] – 48;
if ( v4 )
{
v6 *= 2;
if ( (signed int)v6 > 9 )
v6 = (signed int)v6 % 10 + 1;
}
v4 = v4 == 0;
v3 += v6;
}
result = v3 % 10 == 0;
}
else
{
result = 0;
}
}
else
{
result = 0;
}
return result;
}

The BlackPOS sample would align more with a close (classic) implementation of Luhn’s. Our MEMLOG.A sample is using the idea of Luhn’s with a different implementation.

While this is just one small piece of the functionality of these two families of malware, it helps highlight the differences both stylistically and functionally.

Chasing these algorithms will help in tracking the different evolutions of this malware (and algorithm) over time. By pulling indicators of longevity like this algorithm from known malware, we can push that defense out to our clients. Now they’re protected against what hit Home Depot and any other variant that follows.

Related Articles:

Equifax: A Case Study in Vulnerability Management

Three steps to enhancing security solutions

Subscribe to our blog