Reputation: 33
I don't really know how to title the question, the thing is that I am seeing some serious magic going on there on the following piece of code.
Here I put all the relevant pieces of code, and their output.
void persist_receipt(Receipt * receipt, char * path)
{
int i, fd;
unsigned char block_fname[64];
fd = open( ".receipt", O_RDWR | O_CREAT, 0777);
printf("1.fd=%i\n", fd);
// Write receipt header
write(fd, receipt->hash, 32);
write(fd, receipt->name, 256);
write(fd, &receipt->size, sizeof(int));
printf("2.fd=%i\n", fd);
for(i=0; i<receipt->size; i++)
{
printf("3.fd=%i\n", fd);
sha2hexf(block_fname, receipt->blocks[i].hash);
printf("4.fd=%i\n", fd);
write(fd, block_fname, 64);
}
close(fd);
}
Now let me show you the ouput of this piece of code:
1.fd=4
2.fd=4
3.fd=4
4.fd=0
85a2c67fe7f3dc586a0f231d0cc845e7094408769c8391da18d1ed35c7b1cb3c3.fd=0
4.fd=0
cbc6286fedb70a703f403e507e4daca7bb4a493cdd4d0f0c1787e56256afe5fd3.fd=0
4.fd=0
c364417c27bd887142e6c2de1f7a5b777d604c9df8bcd40bb1a20623b38de82b3.fd=0
What is going on with this random file descriptor loosing it's value? Due to him randomly chaning his value to 0 it outputs to the console the hashses, but it should not happend !
Here comes the fun part ! If I just declare a new variable. Let's say I declare a new integer like so:
void persist_receipt(Receipt * receipt, char * path)
{
int i, fd, p;
unsigned char block_fname[64];
fd = open( ".receipt", O_RDWR | O_CREAT, 0777);
printf("1.fd=%i\n", fd);
// Write receipt header
write(fd, receipt->hash, 32);
write(fd, receipt->name, 256);
write(fd, &receipt->size, sizeof(int));
printf("2.fd=%i\n", fd);
for(i=0; i<receipt->size; i++)
{
printf("3.fd=%i\n", fd);
sha2hexf(block_fname, receipt->blocks[i].hash);
printf("4.fd=%i\n", fd);
write(fd, block_fname, 64);
}
close(fd);
}
As you see, now I declared a 'p' variable, let's compile and run it again, oh boy.
1.fd=4
2.fd=4
3.fd=4
4.fd=4
3.fd=4
4.fd=4
3.fd=4
4.fd=4
3.fd=4
4.fd=4
...
I hope somebody can even explain what is going on behind the scenes. Because this seems some pretty dark magic to me, right there. I suspect there is something suspicious 'sha2hexf' function, so here I put the code as well, specially the suspicious part is the sprintf call inside.
void sha2hexf(unsigned char *outbuf, unsigned char *hash) {
int i;
for (i = 0; i < 32; i++) {
sprintf((char*)outbuf, "%.2x", hash[i]);
outbuf += 2;
}
}
Is there a real explanation?
Upvotes: 0
Views: 79
Reputation: 11206
sha2hexf is writing over outbuf's boundaries (aka block_fname) because sprintf appends "\0" in every single loop (which you take care of by incrementing outbuf, but not in the last loop run!). So the buffer you need accounts for 65 characters.
Upvotes: 1
Reputation: 63481
Your function sha2hexf
is quite clearly overrunning the buffer you passed in. It is null-terminating the 64-byte string (so you need at least 65 bytes in the buffer).
Often a compiler lays out the stack in reverse, so you would get:
block_fname (64 bytes) | fd (4 bytes) | i (4 bytes)
^ Overflow hits the first byte of 'fd', which zeros it
a little-endian architecture (if fd less than 256).
Upvotes: 1