Convert int to string in hex format - c

While I was trying to do a smash-stacking exploit just like this article: http://www.cs.wright.edu/people/faculty/tkprasad/courses/cs781/alephOne.html, I ran across a problem of needing to convert the stack pointer into a string.
I know how to print out an int in a hex format (using printf), but not how to store it as an internal string representation. I need to store it internally as a string so I can pass it into the memcpy function.
The theoretical function I need is "convertFromIntToHexCharStar" below.
unsigned long NOPSledPointer = get_sp() + 150;
char * address = convertFromIntToHexCharStar(NOPSledPointer);
It is intended to work with this function as the argument. It gives the stack pointer.
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
I want to convert the stack pointer into a hex char* so I can do memcpy like this:
char buffer[517];
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* Fill the buffer with appropriate contents here */
memcpy((void*) buffer, (void*) address, 4);
I need to fill in the memory with the address represented in hex, because I know that it has worked in the past.
So, what I'm asking is for help with either converting it to a string, or another easier way to do this NOP sled (that is my real problem I'm trying to solve). I was going to fill in the address multiple times so it increases the odds of overwriting the return address on the stack, but for brevity I only gave one line of code writing "address" into "buffer."
I have already searched stackoverflow & google and couldn't find anything. Thanks in advance for your help!

snprintf solved my problem, since I know the size of the stack pointer in advance to be 4 bytes.
This site helped me:
http://www.cplusplus.com/reference/cstdio/snprintf/
And here is the code solution below, with some print statements that I used to make sure it worked correctly.
#include <stdio.h>
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
int main()
{
unsigned long numberToConvert = get_sp();
char address[9];
snprintf(address, 9, "%08lX", numberToConvert);
printf("Number To Convert: %lu \n", numberToConvert);
printf("Expected hex number: %08lX \n", numberToConvert);
printf("Actual hex number: %s \n", address);
return 0;
}

Related

Function is returning a different value every time?

I'm trying to convert a hexadecimal INT to a char so I could convert it into a binary to count the number of ones in it. Here's my function to convert it into char:
#include <stdio.h>
#include <stdlib.h>
#define shift(a) a=a<<5
#define parity_even(a) a = a+0x11
#define add_msb(a) a = a + 8000
void count_ones(int hex){
char *s = malloc(2);
sprintf(s, "0x%x", hex);
free(s);
printf("%x", s);
};
int main() {
int a = 0x01B9;
shift(a);
parity_even(a);
count_ones(a);
return 0;
}
Every time I run this, i always get different outputs but the first three hex number are always the same. Example of outputs:
8c0ba2a0
fc3b92a0
4500a2a0
d27e82a0
c15d62a0
What exactly is happening here? I allocated 2 bytes for the char since my hex int is 2 bytes.
It's too long to write a comment so here goes:
I'm trying to convert a hexadecimal INT
int are stored as a group of value, padding (possible empty) and sign bits, so is there no such thing as a hexadecimal INT but you can represent (print) a given number in the hexadecimal format.
convert a ... INT to a char
That would be lossy conversion as an int might have 4 bytes of data that you are trying to cram into a 1 byte. char specifically may be signed or unsigned. You probably mean string (generic term) or char [] (standard way to represent a string in C).
binary to count the number of ones
That's the real issue you are trying to solve and this is a duplicate of:
How to count the number of set bits in a 32-bit integer?
count number of ones in a given integer using only << >> + | & ^ ~ ! =
To address the question you ask:
Need to allocate more than 2 bytes. Specifically ceil(log16(hex)) + 2 (for 0x) + 1 (for trailing '\0').
One way to get the size is to just ask snprintf(s, 0, ...)
then allocate a suitable array via malloc (see first implementation below) or use stack allocated variable length array (VLA).
You can use INT_MAX instead of hex to get an upper
bound. log16(INT_MAX) <= CHAR_BIT * sizeof(int) / 4 and the
latter is a compile time constant. This means you can allocate your string on stack (see 2nd implementation below).
It's undefined behavior to use a variable after it's deallocated. Move free() to after the last use.
Here is one of the dynamic versions mentioned above:
void count_ones(unsigned hex) {
char *s = NULL;
size_t n = snprintf(s, 0, "0x%x", hex) + 1;
s = malloc(n);
if(!s) return; // memory could not be allocated
snprintf(s, n, "0x%x", hex);
printf("%s (size = %zu)", s, n);
free(s);
};
Note, I initialized s to NULL which would cause the first call to snprintf() to return an undefined value on SUSv2 (legacy). It's well defined on c99 and later. The output is:
0x3731 (size = 7)
And the compile-time version using a fixed upper bound:
#include <limits.h>
// compile-time
void count_ones(unsigned hex) {
char s[BIT_CHAR * sizeof(int) / 4 + 3];
sprintf(s, "0x%x", hex);
printf("%s (size = %zu)", s, n);
};
and the output is:
0x3731 (size = 11)
Your biggest problem is that malloc isn't allocating enough. As Barmar said, you need at least 7 bytes to store it or you could calculate the amount needed. Another problem is that you are freeing it and then using it. It is only one line after the free that you use it again, which shouldn't have anything bad happen like 99.9% of the time, but you should always free after you know you are done using it.

Buffer Overflow to Modify the Return Address

I'm needing to modify the return address so I can call print_good function. I need an offset value, and a hex value to store to do so. The offset that I calculated from using obj is 0xcd, which was gotten 0x40074e(the puts function which I believe prints out try again) minus 400686(The address of the print_good function that I want to call). The hex value that I believe is correct is 400686, which is the address of the print_good value. Putting the offset value I got and the hex value I got doesn't give the correct answer.
I'm pretty sure the hex value is 0x400686, but correct me if I'm wrong. The offset value I believe could be off.
I'm given the code and the executable. I need to find the password which is an offset value and a hex value. I got the addresses using objdump and looking at its code.
If you want to try it yourself to help me, here's the file to download the executable:
The executable:
https://www.mediafire.com/file/disui6pwcb55ing/Ch3_07_CanaryBypass
The c code:
https://www.mediafire.com/file/yu3j3dxg476qy8c/Ch3_07_CanaryBypass.c
The c Code written here:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#define USERDEF 30
char msg[] =
"Stack canaries and non-executable stacks make stack exploitation difficult. Such\n"
"techniques, however, do not protect against return-oriented programming where\n"
"only the return addresses on the stack are targeted. In this level, you control\n"
"a single write into a vulnerable buffer in the function prompt_user. Overflow\n"
"the buffer to modify the return address beyond the stack canary so that it\n"
"points to a function of your choice. The level will prompt you with an offset\n"
"(in decimal) from the beginning of the buffer that will be written into followed\n"
"by a hexadecimal value that will be written there (e.g. scanf(\"%d %x\");).\n"
"The program will then write the hexadecimal value to a location computed\n"
"using the offset. To determine how close you are, examine the pointer\n"
"being used to write into the stack and how far away it is from the value\n"
"of $rsp when the retq instruction at the end of prompt_user is reached.\n\n";
void print_good() {
printf("Good Job.\n");
exit(0);
}
void print_msg() {
printf("%s",msg);
}
void prompt_user() {
char buffer[30];
int offset;
char *user_addr;
char **over_addr;
printf("Enter the password: ");
scanf("%d %lx", &offset, (unsigned long *) &user_addr);
over_addr = (char **) (buffer + offset);
*over_addr = user_addr;
}
int main(int argc, char *argv[]) {
print_msg();
prompt_user();
printf("Try again.\n");
return 0;
}

Format specifier %u used with sprintf is creating crash

When I used %u in sprintf() application gets crashed, it's working fine with %d
See the code:
#include <stdio.h>
#include <string.h>
main()
{
unsigned char dAddr[4];
unsigned char sMask[4];
unsigned char nHop[4];
memset(dAddr,0,sizeof(dAddr));
memset(sMask,0,sizeof(sMask));
memset(nHop,0,sizeof(nHop));
unsigned int u4IpDAddr = 0x01020304;
unsigned int u4IpSNetMask = 0xffff01ff;
unsigned int u4NHopGt = 0x01020304;
char *dip = (char *)&u4IpDAddr;
char *smk = (char *)&u4IpSNetMask;
char *nhp = (char *)&u4NHopGt;
sprintf(dAddr, "%u.%u.%u.%u", dip[3], dip[2], dip[1], dip[0]); //if I used %d.%d.%d.%d its working fine
sprintf(sMask, "%u.%u.%u.%u", smk[3], smk[2], smk[1], smk[0]); //if I used %d.%d.%d.%d its working fine
sprintf(nHop, "%u.%u.%u.%u", nhp[3], nhp[2], nhp[1], nhp[0]); //if I used %d.%d.%d.%d its working fine
printf("SAM: func %s line %d IpDAddr %s Mask %s NHop %s\n",__func__,__LINE__,dAddr,sMask,nHop);
}
when I declared a pointer's with following manner its working fine for %u.%u.%u.%u format
unsigned char *dip = (unsigned char *)&u4IpDAddr;
unsigned char *smk = (unsigned char *)&u4IpSNetMask;
unsigned char *nhp = (unsigned char *)&u4NHopGt;
Can any one explain what is happening when I used char pointers?
In your case
unsigned char dAddr[4];
unsigned char sMask[4];
unsigned char nHop[4];
are not sufficient to hold the lexicographical output.
When you're using those arrays as the destination string in sprintf(), essentially, you're overrunning the allocated memory, creating undefined behaviour.
You need to allocate more memory to use those arrays as the destination of sprintf().
If char is signed on your platform, then char value that you "hack out" of your u4IpSNetMask are more than likely to be negative, since you have bytes that begin with 0xF... in u4IpSNetMask. When you send such char values to sprintf they get converted to negative int values and then reinterpreted as unsigned values by your %u specifier. The behavior is actually undefined - it is illegal to sprintf negative int values with %u. However, in practice you usually end up with a huge positive values that require many characters to represent. These representations easily overflow your destination buffers, destroy the program stack and cause your program to crash.
You can see for yourself what your sprintf calls generate on a typical platform: http://coliru.stacked-crooked.com/a/6aec03cfdf28f8b2
The middle sprintf produces 4294967295.4294967295.1.4294967295. And you expected this monster to fit into buffer sMask of only 4 characters long?
Moreover, the same kind of overflow happens with %d as well, but the string representation produced by %d is shorter (-1 in place of 4294967295) an the damage is smaller, which is probably why the program sort of limps to the end without crashing. But that does not change the fact that string 1.2.3.4 requires a char buffer of at least 8 characters long. You provided only 4.
In other words, your program is as broken with %d as it is broken with %u. If it did not crash with %d, it is just out of random luck.

sprintf is outputting some strange data

I am working an embedded project which involves reading/writing a struct into EEPROM. I am using sprintf to make it easy to display some debugging information.
There are two problems with this code for some reason. The first; sprintf is printing a very strange output. When I print 'addr++' it will follow a pattern '0, 1, 2, 3, 4, 32, ...' which doesn't make sense.
void ee_read(char * buf, unsigned int addr, unsigned int len) {
unsigned int i;
sprintf(bf1, "Starting EEPROM read of %u bytes.\r\n", len); // Debug output
debugr(bf1);
IdleI2C1();
StartI2C1();
WriteI2C1(EE_ADDR | EE_W);
IdleI2C1();
WriteI2C1((unsigned char)addr>>8); // Address to start reading data from
IdleI2C1();
WriteI2C1((unsigned char)addr&0xFF);
IdleI2C1();
RestartI2C1();
WriteI2C1(EE_ADDR | EE_R);
IdleI2C1();
for (i=0; i<len; i++) {
buf[i] = ReadI2C1(); // Read a byte from EEPROM
sprintf(bf1, "Addr: %u Byte: %c\r\n", addr, buf[i]); // Display the read byte and the address
debugr(bf1);
addr++; // Increment address
IdleI2C1();
if (i == len-1) { // This makes sure the last byte gets 'nAcked'
NotAckI2C1();
} else {
AckI2C1();
}
}
StopI2C1();
}
The output from the above is here: https://gist.github.com/3803316 Please note that the about output was taken with %x for the address value (so addr is hex)
The second problem, which you may have noticed with the output, is that it doesn't stop when i > len. It continues further than the output I have supplied, and doesn't stop until the microcontroller's watch dog restarts.
Edit:
Calling the function
Location loc;
ee_read(&loc, 0, sizeof(Location));
Declarations:
struct location_struct {
char lat[12]; // ddmm.mmmmmm
char latd[2]; // n/s
char lon[13]; // dddmm.mmmmmm
char lond[2]; // e/w
char utc[11]; // hhmmss.sss
char fix[2]; // a/v
};
typedef struct location_struct Location;
char bf1[BUFFER_SIZE];
I don't think it's a race condition. I disable the interrupts which use bf1. Even then, it would corrupt the whole debug string if that happened, and it certainly wouldn't be so repeatable.
Edit
The value of addr starts as zero, which can be seen here: https://gist.github.com/3803411
Edit
What this is supposed to do it copy the location structure byte by byte into the EEPROM, and then recall it when it is needed.
Closure
So I never did solve this problem. The project moved away from the EEPROM, and I have since changed OS, compiler and IDE. It's unlikely I will replicate this problem.
I'll tell you one thing wrong with your code, this line:
(unsigned char)addr>>8
doesn't do what you seem to need.
It converts the value in addr into an unsigned char which (assuming 8-bit char and either 16-bit int or only using the lower 16 bits of a wider int), will will always give you the lower eight bits.
If you then right shift that by eight bits, you'll always end up with zero.
If your intent is to get the upper eight bits of the address, you need to use:
(unsigned char)(addr>>8)
so that the shift is done first.

Format String Attack in C

I'm studying a security unit and I'm attempting to understand format string attacks. Could somebody please attempt to explain this to me?
The following code is taken from: http://julianor.tripod.com/bc/tn-usfs.pdf:
/*
* fmtme.c
* Format a value into a fixed-size buffer
*/
#include <stdio.h>
int
main(int argc, char **argv)
{
char buf[100];
int x;
if(argc != 2)
exit(1);
x = 1;
snprintf(buf, sizeof buf, argv[1]);
buf[sizeof buf - 1] = 0;
printf("buffer (%d): %s\n", strlen(buf), buf);
printf("x is %d/%#x (# %p)\n", x, x, &x);
return 0;
}
As I understand it, the %n format specifier is used to read a specified address back into memory, then when printf pops values off the stack, it should read our address. I can't seem to pull this off.
In the document, the following example is provided:
perl -e 'system "./fmtme", "\x58\x74\x04\x08%d%n"'
Where did \x58\x74\x04\x08%d%n come from?
"\x58\x74\x04\x08%d%n" is the "shell code".
The exploit is explained very carefully in that document. I suppose it expects you to have some understanding of the typical layout of stack frames, which also is explained in the table . Keep in mind that stack addresses typically grows downwards, which means that a function call that "pops" more arguments than was actually passed to it will start reading local variables from the stack frame below its own. This is what this shell code exploits.
It puts an address in the first 4 bytes of buf (because snprintf prints it into there) and then it skips the x variable (from the frame below it) and finally reads the address from the first part of buf (but interpreted as a pointer) and write a value to it, via the %n format code.

Resources