I'm trying to access individual bytes of a wide-char array so that I can send it via winsock, and this is what I've got so far:
WCHAR* buffer_in_bytes = (WCHAR*)msc->wcArray;
unsigned char l;
for (unsigned int i = 0; i <= (msc->bSize*2); i++ )
{
l = (unsigned char)(*(buffer_in_bytes +i));
char s[256] ;
_itoa(l,s,16);
OutputDebugString(s);
}
They array contains a series of a(s) (aaaaaaaaaaaaaaaaaaaa....), and I would expect to see 00 61 00 61 00 61 as a result I get 61 61 61 61 61 61
Any ideas why?
Each element contains an 'a', or ASCII 61, which is what you see printed. I don't know why you would expect to see these interspersed with 0's.
Related
I am currently working with oneof properties. I am able to encode them without issue, however, decoding seems to be an issue. I fail to understand why it doesn't work.
My proto file looks like this:
syntax = "proto2";
message stringCallback{
required string name = 1;
required string surname = 2;
required int32 age = 3;
repeated sint32 values = 4;
repeated metrics metric_data = 5;
oneof payload {
int32 i_val = 6;
float f_val = 7;
string msg = 8;
}
}
message metrics{
required int32 id = 1;
required string type = 2;
required sint32 value = 3;
}
Whenever I send from a C# application a message containing in the payload an integer, there is no issue decoding. I get the right int value and which_payload value as well.
I then tried to send a float. This resulted in a value which was not corresponding to the value I send through C# (which makes sense because I use the "standard decoder" which means that it treats it as an int instead of a fixed32) I don't know how to tell the decoder to decode this value with the fixed32 option.
And finally sending a payload which contains a message resulted in an incorrect which_payload value (Type None: 0) and no corresponding message. Even though before the decode function I assigned a callback function to decode a string (works perfectly).
Additional info:
This is the byte array which I send to the Nanopb code containing a string in the payload:
0A 04 4B 65 65 73 12 07 76 61 6E 20 44 61 6D 18 34 20 02 20 04 20 06 20 08 20 0A 20 0C 20 0E 20 10 20 12 20 14 20 16 20 18 2A 0C 08 01 12 06 53 65 6E 73 6F 72 18 04 2A 0A 08 02 12 04 44 61 74 61 18 0A 2A 0E 08 03 12 08 57 69 72 65 6C 65 73 73 18 0E 2A 0D 08 04 12 07 54 65 73 74 69 6E 67 18 04 2A 10 08 05 12 0A 46 72 6F 6E 74 20 64 6F 6F 72 18 0A 2A 1B 08 06 12 15 54 68 69 73 20 69 73 20 61 20 72 61 6E 64 6F 6D 20 6E 61 6D 65 18 0E 42 10 48 65 6C 6C 6F 20 66 72 6F 6D 20 6F 6E 65 6F 66
I get from an online decoder the correct decoded variables but not on Nanopb. What am I supposed to do?
EDIT:
As per request, my decoder test function:
void test_decode(byte* payload, unsigned int length){
IntArray I_array = {0, 0};
MetricArray M_array = {0,0};
char name[MAX_STRING_LENGTH];
char surname[MAX_STRING_LENGTH];
char msg[MAX_STRING_LENGTH];
stringCallback message = stringCallback_init_zero;
message.name.funcs.decode = String_decode;
message.name.arg = &name;
message.surname.funcs.decode = String_decode;
message.surname.arg = &surname;
message.values.funcs.decode = IntArray_decode;
message.values.arg = &I_array;
message.metric_data.funcs.decode = MetricArray_decode;
message.metric_data.arg = &M_array;
message.payload.msg.arg = &msg;
message.payload.msg.funcs.decode = String_decode;
pb_istream_t istream = pb_istream_from_buffer(payload, length);
if(!pb_decode(&istream, stringCallback_fields, &message)){
Serial.println("Total decoding failed!");
return;
}
Serial.println(name);
Serial.println(surname);
Serial.println(message.age);
Serial.println(I_array.count);
Serial.println(M_array.count);
Serial.println();
MetricArray_print(&M_array);
Serial.println();
Serial.println("Oneof: ");
Serial.println(message.which_payload);
}
After some searching and testing I found a workaround!
I look at these examples, and figured that there are possibilities of having callbacks in oneof fields. There is a possibility to add a Nanopb option to the proto file which tells the message that it should generate a callback.
The option:
option (nanopb_msgopt).submsg_callback = true;
By adding this line to the proto file it will generate (to my understanding) a set-up callback. This callback gets called at the start of decoding the message. This gives us the opportunity to setup different callbacks for different fields in the oneof depending on the type we are decoding.
The problem before with oneof is that it was impossible to assign callback functions to the fields of the oneof type since they all share the same memory space. But by having this set-up callback we can actually have a look at what we are receiving and assign a callback accordingly.
However, there is a catch. I found out that this option will not work on anything other than messages in the oneof. This means no direct callback type can be assigned to a oneof field!
The workaround I used is to encapsulate the wanted callback in a message. This will trigger the set-up callback which then can be used to assign the correct callback function in the oneof.
EXAMPLE:
Lets take this proto file:
syntax = "proto2";
message callback{
required string name = 1;
required string surname = 2;
required int32 age = 3;
repeated sint32 values = 4;
repeated metrics metric_data = 5;
oneof payload {
int32 i_val = 6;
float f_val = 7;
string msg = 8;
payloadmsg p_msg = 9;
payloadmsg2 p_msg2 = 10;
}
}
message metrics{
required int32 id = 1;
required string type = 2;
required sint32 value = 3;
}
message payloadmsg{
required int32 id = 1;
required string type = 2;
required string msg = 3;
repeated sint32 values = 4;
}
message payloadmsg2{
required int32 id = 1;
required string type = 2;
required string msg = 3;
repeated sint32 values = 4;
}
I gave the strings in this proto file a maximum length which removed their callback type and exchanged it for a character array.
For testing purposes I didn't assign a size to the integer arrays in the payloadmsg messages.
The goal is to decode the arrays stored in the payloadmsg messages depending on the oneof type received (payloadmsg or payloadmsg2)
Then the set-up callback has to be created:
bool Oneof_decode(pb_istream_t *stream, const pb_field_t *field, void** arg){
Callback* msg = (Callback*)field->message;
switch(field->tag){
case stringCallback_p_msg_tag:{
Serial.println("Oneof type: p_msg detected!");
payloadmsg* p_message = (payloadmsg*)field->pData;
IntArray* array = (IntArray*)*arg;
p_message->values.arg = array;
p_message->values.funcs.decode = IntArray_decode;
break;
}
case stringCallback_p_msg2_tag:{
Serial.println("Oneof type: p_msg2 detected!");
payloadmsg2* p_message2 = (payloadmsg2*)field->pData;
IntArray* array = (IntArray*)*arg;
p_message2->values.arg = array;
p_message2->values.funcs.decode = IntArray_decode;
break;
}
}
return true;
}
We look at the tag we receive while decoding to see which type of callback has to be assigned. This is done by accessing the field. By using a switch case we can decide, according to the field tag, what decode callback function to assign. We pass the arguments and decoder functions like normal, after that everything is set-up correctly.
Finally we assign this callback set-up to the compiler generated variable called cb_payload. This variable will be added to your message struct when you put in the option in the protofile. This is how to assign the set-up callback:
message.cb_payload.arg = &I_array;
message.cb_payload.funcs.decode = Oneof_decode;
pb_istream_t istream = pb_istream_from_buffer(payload, length);
if(!pb_decode(&istream, stringCallback_fields, &message)){
Serial.println("Total decoding failed!");
return;
}
I pass my own IntArray struct to the cb_payload function as an argument to then pass it on to the correctly assigned decoder.
The result is that whenever I decode payloadmsg or payloadmsg2 the correct decoder gets assigned and the right values are being decoded into the structs.
I have a raw ECDSA signature: R and S values. I need a DER-encoded version of the signature. Is there a straightforward way to do this in openssl using the c interface?
My current attempt is to use i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp) to populate an ECDSA_SIG*. The call returns non-zero but the target buffer doesn't seem to be changed.
I'm intiailly filling my ECDSA_SIG wtih r and s values. I don't see any errors. The man page says r and s should be allocated when I call ECDSA_SIG_new
ECDSA_SIG* ec_sig = ECDSA_SIG_new();
if (NULL == BN_bin2bn(sig, 32, (ec_sig->r))) {
dumpOpenSslErrors();
}
DBG("post r :%s\n", BN_bn2hex(ec_sig->r));
if (NULL == BN_bin2bn(sig + 32, 32, (ec_sig->s))) {
dumpOpenSslErrors();
}
DBG("post s :%s\n", BN_bn2hex(ec_sig->s));
S and R are now set:
post r :397116930C282D1FCB71166A2D06728120CF2EE5CF6CCD4E2D822E8E0AE24A30
post s :9E997D4718A7603942834FBDD22A4B856FC4083704EDE62033CF1A77CB9822A9
now to make the encoded signature.
int sig_size = i2d_ECDSA_SIG(ec_sig, NULL);
if (sig_size > 255) {
DBG("signature is too large wants %d\n", sig_size);
}
DBG("post i2d:%s\n", BN_bn2hex(ec_sig->s));
s hasn't changed:
post i2d:9E997D4718A7603942834FBDD22A4B856FC4083704EDE62033CF1A77CB9822A9
At this point I have more than enough bytes ready and I set the target to all 6s so it's easy to see what changes.
unsigned char* sig_bytes = new unsigned char[256];
memset(sig_bytes, 6, 256);
sig_size = i2d_ECDSA_SIG(ec_sig, (&sig_bytes));
DBG("New size %d\n", sig_size);
DBG("post i2d:%s\n", BN_bn2hex(ec_sig->s));
hexDump("Sig ", (const byte*)sig_bytes, sig_size);
The new size is 71
New size 71 and s iis stiill the same:
`post i2d:9E997D4718A7603942834FBDD22A4B856FC4083704EDE62033CF1A77CB9822A9`
The hex dump is all 6s.
--Sig --
0x06: 0x06: 0x06: 0x06: 0x06: 0x06: 0x06: 0x06:
0x06: ...
The dump is still all 6s even though the call didn't return 0. What am I missing tying to DER encode this raw signature?
i2d_ECDSA_SIG modifies its second argument, increasing it by the size of the signature. From ecdsa.h:
/** DER encode content of ECDSA_SIG object (note: this function modifies *pp
* (*pp += length of the DER encoded signature)).
* \param sig pointer to the ECDSA_SIG object
* \param pp pointer to a unsigned char pointer for the output or NULL
* \return the length of the DER encoded ECDSA_SIG object or 0
*/
int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);
So you need to keep track of the original value of sig_bytes when you call i2d_ECDSA_SIG:
int sig_size = i2d_ECDSA_SIG(ec_sig, NULL);
unsigned char *sig_bytes = malloc(sig_size);
unsigned char *p;
memset(sig_bytes, 6, sig_size);
p = sig_bytes;
new_sig_size = i2d_ECDSA_SIG(_sig, &p);
// The value of p is now sig_bytes + sig_size, and the signature resides at sig_bytes
Output:
30 45 02 20 39 71 16 93 0C 28 2D 1F CB 71 16 6A
2D 06 72 81 20 CF 2E E5 CF 6C CD 4E 2D 82 2E 8E
0A E2 4A 30 02 21 00 9E 99 7D 47 18 A7 60 39 42
83 4F BD D2 2A 4B 85 6F C4 08 37 04 ED E6 20 33
CF 1A 77 CB 98 22 A9
This function is supposed to search through a text file for the new line character. When it finds the newline character, it increments the newLine counter, and when there are more than 2 consecutive blank new lines, its suppose to squeeze all the blank lines into just one blank line.
In my code if there are 2 new lines it's suppose to get rid of them and squeeze them into one, for testing purposes I also have it printing "new line" when it reaches the newLine < 2 condition. Right now it prints new line for every new line, whether its blank or not, and its not getting rid of the extra new lines. What am I doing wrong?
EDIT: HERE IS MY FULL CODE
http://pastebin.com/bsD3b38a
So basically the program is suppose to concatenate two files together and than perform various operations on them, like what I'm trying to do which is get rid of multiple consecutive blank new lines.
So in order to execute it in cygwin I do
./a -s file1 file2
Its suppose to concatenate file1 and file2 together into a file called contents.txt and than get rid of the consecutive new lines and display them on my cygwin terminal (stdout). (the -s calls the function to get rid of the consecutive lines). The third and fourth arguments passed in (file1 and file2) are the two files its suppose to concatenate together into one file called contents.txt The squeeze_lines function than reads the contents.txt file and is suppose to squeeze new lines. You can see below for an example for the contents I put in file1.txt. file2.txt just has a bunch of words followed by empty new lines.
int newLine = 1;
int c;
if ((fileContents = fopen("fileContents.txt", "r")) == 0)
{
perror("fopen");
return 1;
}
while ((c = fgetc(fileContents)) != EOF)
{
if (c == '\n')
{
newLine++;
if (newLine < 2)
{
printf("new line");
putchar(c);
}
}
else
{
putchar(c);
newLine = 0;
}
}
The file the program reads in a .txt file with these contents. Its suppose to read the file, get rid of the leading, and consecutive new lines, and output the new formatted contents to stdout on my cywgin terminal.
/* hello world program */
#include <stdio.h>
tab
2tabs
Diagnosis
The logic looks correct if you have Unix line endings. If you have Windows CRLF line endings but are processing the file on Unix, you have a CR before each LF, and the CR resets newLine to zero, so you get the message for each newline.
This would explain what you're seeing.
It would also explain why everyone else is saying your logic is correct (it is — provided that the lines end with just LF and not CRLF) but you are seeing an unexpected result.
How to resolve it?
Fair question. One major option is to use dos2unix or an equivalent mechanism to convert the DOS file into a Unix file. There are many questions on the subject on SO.
If you don't need the CR ('\r' in C) characters at all, you can simply delete (not print, and not zero newLine) those.
If you need to preserve the CRLF line endings, you'll need to be a bit more careful. You'll have to record that you got a CR, then check that you get an LF, then print the pair, and then check whether you get any more CRLF sequences and suppress those, etc.
Working code — dupnl.c
This program only reads from standard input; this is more flexible than
only reading from a fixed file name. Learn to avoid writing code which
only works with one file name; it will save you lots of recompilation
over time. Th code handles Unix-style files with newlines ("\n") only
at the end; it also handles DOS files with CRLF ("\r\n") endings; and
it also handles (old style) Mac (Mac OS 9 and earlier) files with CR
("\r") line endings. In fact, it handes arbitrary interleavings of
the different line ending styles. If you want enforcement of a single
mode, you have to do some work to decide which mode, and then use an
appropriate subset of this code.
#include <stdio.h>
int main(void)
{
FILE *fp = stdin; // Instead of fopen()
int newLine = 1;
int c;
while ((c = fgetc(fp)) != EOF)
{
if (c == '\n')
{
/* Unix NL line ending */
if (newLine++ == 0)
putchar(c);
}
else if (c == '\r')
{
int c1 = fgetc(fp);
if (c1 == '\n')
{
/* DOS CRLF line ending */
if (newLine++ == 0)
{
putchar(c);
putchar(c1);
}
}
else
{
/* MAC CR line ending */
if (newLine++ == 0)
putchar(c);
if (c1 != EOF && c1 != '\r')
ungetc(c1, stdin);
}
}
else
{
putchar(c);
newLine = 0;
}
}
return 0;
}
Example run — inputs and outputs
$ cat test.unx
data long enough to be seen 1 - Unix
data long enough to be seen 2 - Unix
data long enough to be seen 3 - Unix
data long enough to be seen 4 - Unix
data long enough to be seen 5 - Unix
$ sed 's/Unix/DOS/g' test.unx | ule -d > test.dos
$ cat test.dos
data long enough to be seen 1 - DOS
data long enough to be seen 2 - DOS
data long enough to be seen 3 - DOS
data long enough to be seen 4 - DOS
data long enough to be seen 5 - DOS
$ sed 's/Unix/Mac/g' test.unx | ule -m > test.mac
$ cat test.mac
$ ta long enough to be seen 5 - Mac
$ odx test.mac
0x0000: 0D 0D 64 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 ..data long enou
0x0010: 67 68 20 74 6F 20 62 65 20 73 65 65 6E 20 31 20 gh to be seen 1
0x0020: 2D 20 4D 61 63 0D 0D 64 61 74 61 20 6C 6F 6E 67 - Mac..data long
0x0030: 20 65 6E 6F 75 67 68 20 74 6F 20 62 65 20 73 65 enough to be se
0x0040: 65 6E 20 32 20 2D 20 4D 61 63 0D 64 61 74 61 20 en 2 - Mac.data
0x0050: 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 74 6F 20 62 long enough to b
0x0060: 65 20 73 65 65 6E 20 33 20 2D 20 4D 61 63 0D 64 e seen 3 - Mac.d
0x0070: 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 ata long enough
0x0080: 74 6F 20 62 65 20 73 65 65 6E 20 34 20 2D 20 4D to be seen 4 - M
0x0090: 61 63 0D 0D 0D 0D 64 61 74 61 20 6C 6F 6E 67 20 ac....data long
0x00A0: 65 6E 6F 75 67 68 20 74 6F 20 62 65 20 73 65 65 enough to be see
0x00B0: 6E 20 35 20 2D 20 4D 61 63 0D 0D 0D n 5 - Mac...
0x00BC:
$ dupnl < test.unx
data long enough to be seen 1 - Unix
data long enough to be seen 2 - Unix
data long enough to be seen 3 - Unix
data long enough to be seen 4 - Unix
data long enough to be seen 5 - Unix
$ dupnl < test.dos
data long enough to be seen 1 - DOS
data long enough to be seen 2 - DOS
data long enough to be seen 3 - DOS
data long enough to be seen 4 - DOS
data long enough to be seen 5 - DOS
$ dupnl < test.mac
$ ta long enough to be seen 5 - Mac
$ dupnl < test.mac | odx
0x0000: 64 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 data long enough
0x0010: 20 74 6F 20 62 65 20 73 65 65 6E 20 31 20 2D 20 to be seen 1 -
0x0020: 4D 61 63 0D 64 61 74 61 20 6C 6F 6E 67 20 65 6E Mac.data long en
0x0030: 6F 75 67 68 20 74 6F 20 62 65 20 73 65 65 6E 20 ough to be seen
0x0040: 32 20 2D 20 4D 61 63 0D 64 61 74 61 20 6C 6F 6E 2 - Mac.data lon
0x0050: 67 20 65 6E 6F 75 67 68 20 74 6F 20 62 65 20 73 g enough to be s
0x0060: 65 65 6E 20 33 20 2D 20 4D 61 63 0D 64 61 74 61 een 3 - Mac.data
0x0070: 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 74 6F 20 long enough to
0x0080: 62 65 20 73 65 65 6E 20 34 20 2D 20 4D 61 63 0D be seen 4 - Mac.
0x0090: 64 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 data long enough
0x00A0: 20 74 6F 20 62 65 20 73 65 65 6E 20 35 20 2D 20 to be seen 5 -
0x00B0: 4D 61 63 0D Mac.
0x00B4:
$
The lines starting $ ta are where the prompt overwrites the previous output (and the 'long enough to be seen' part is because my prompt is normally longer than just $).
odx is a hex dump program. ule is for 'uniform line endings' and analyzes or transforms data so it has uniform line endings.
Usage: ule [-cdhmnsuzV] [file ...]
-c Check line endings (default)
-d Convert to DOS (CRLF) line endings
-h Print this help and exit
-m Convert to MAC (CR) line endings
-n Ensure line ending at end of file
-s Write output to standard output (default)
-u Convert to Unix (LF) line endings
-z Check for zero (null) bytes
-V Print version information and exit
What the sample code resolved is:
1) squeeze the consecutive a few '\n' to just one '\n'
2) Get rid the leading '\n' at the beginning if there is any.
input: '\n\n\naa\nbb\n\ncc'
output: aa'\n'
bb'\n' //notice, there is no blank line here
cc
If it was the aim, then your code logic is correct for it.
By defining newLine = 1 , it will get rid of any leading '\n' of the
input txt.
And when there is a remained '\n' after processing, it will output a new line to give a hint.
Back to the question itself, if the actual aim is to squeeze consecutive blank lines to just one blank line(which needs two consecutive '\n', one for terminate previous line, one for blank line).
1) Let's confirm the input and expected output firstly,
Input text:
aaa'\n' //1st line, there is a '\n' append to 'aaa'
'\n' //2nd line, blank line
bbb'\n' //3rd line, there is a '\n' append to 'bbb'
'\n' //4th line, blank line
'\n' //5th line, blank line
'\n' //6th line, blank line
ccc //7th line,
Expected Output text:
aaa'\n' //1st line, there is a '\n' append to 'aaa'
'\n' //2nd line, blank line
bbb'\n' //3rd line, there is a '\n' append to 'bbb'
'\n' //4th line, blank line
ccc //5th line,
2) If it is the exact program target as above,then
if (c == '\n')
{
newLine++;
if (newLine < 3) // here should be 3 to print '\n' twice,
// one for 'aaa\n', one for blank line
{
//printf("new line");
putchar(c);
}
}
3) If you have to process the Windows format file(with \r\n ending) under Cygwin, then you could do as follows
while ((c = fgetc(fileContents)) != EOF)
{
if ( c == '\r') continue;// add this line to discard possible '\r'
if (c == '\n')
{
newLine++;
if (newLine < 3) //here should be 3 to print '\n' twice
{
printf("new line");
putchar(c);
}
}
else
{
putchar(c);
newLine = 0;
}
}
[EDITED]
The minimal change is:
if ( newLine <= 2)
forgive me and forget the previous code.
a slightly simpler alternative:
int c;
int duplicates=0;
while ((c = fgetc(fileContents)) != EOF)
{
if (c == '\n') {
if (duplicates > 1) continue;
duplicates++;
}
else {
duplicates=0;
}
putchar(c);
}
Dry ran the code:
If file starts with a newline character and newLine is 1:
For the first iteration:
if (c == '\n') //Will be evaluated as true for a new-line character.
{
newLine++; //newLine becomes 2 before next if condition is evaluated.
if (newLine < 2) //False, since newLine is not less than 2, but equal.
{
printf("new line");
putchar(c);
}
}
else //Not entered
{
putchar(c);
newLine = 0;
}
On the second iteration: (Assume that it is a consecutive newline char case)
if (c == '\n') //Will be evaluated as true for a new-line character.
{
newLine++; //newLine becomes 3 before next if condition is evaluated.
if (newLine < 2) //False, since newLine is greater than 2.
{
printf("new line");
putchar(c);
}
}
else //Not entered
{
putchar(c);
newLine = 0;
}
So,
Initialize newLine to 0.
if newline > 2
That should be greater than or equal to if you want to get rid of the second line.
Also you have newline strarting at one, then being incremented to two then reset to zero. Instead I recommend replacing the count with a boolean like
boolean firstNewlineFound = false
Then Whenever you find a newline set it to true; whenever it is true, delete onenewline and set it back to false.
I'm using bufbomb.c to do some buffer overflow attack experimenting.
I successfully used gdb to debug the code. Howeverer; when I run the program directly, I get a "Segmentation fault (core dumped)" when I enter the characters to try the attack.
I used gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1. to build the following.
//bufbomb.c
/* Bomb program that is solved using a buffer overflow attack */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even =1; /* Have read even number of digits */
int otherd =0; /* Other hex digit of pair */
char*sp = dest;
while ((c = getchar()) != EOF && c !='\n') {
if (isxdigit(c)) {
int val;
if ('0'<= c && c <='9')
val = c -'0';
else if ('A'<= c && c <='F')
val = c -'A'+10;
else
val = c -'a'+10;
if (even) {
otherd = val;
even =0;
}
else {
*sp++= otherd *16+ val;
even =1;
}
}
}
*sp++='\0';
return dest;
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
/* $end getbuf-c */
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) &0xFFF);
int*space = (int*) alloca(offset);
*space =0; /* So that don't get complaint of unused variable */
test();
return 0;
}
Then I executed it under gdb:
...> gdb ./bugbomb
...
..run
Type Hex string:30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 d8 bf ff ff 9f 85 04 08 b0 86 04 08 30 31 32 33 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ef be ad de
getbuf returned 0xdeadbeef
[Inferior 1 (process 13530) exited normally]
And then without gdb::
./bufbomb
Type Hex string:30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 d8 bf ff ff 9f 85 04 08 b0 86 04 08 30 31 32 33 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ef be ad de
Segmentation fault (core dumped)
I am looking for some help to resolve the seg-fault.
Run it under gdb with a bigger buffer to see which address it's trying to access to guess the stack offset of the return address used by getbuf().
To bear with small differences in memory offsets that arise from the use of gdb, use a NOP-sled. Your attack buffer should look like this:
|RET ADDRESS x 30 | NOPS (0x90) x 1000 | SHELLCODE|.
The return address should point to the middle of the NOP-sled.
If the execution jumps anywhere in the sled, it will slide to the shellcode.
You are accessing memory that your process doesn't "own".
When you run gdb, the compiler adds stuff (like extra debug info).
You can bypass the segmentation fault by expanding the stack before you attempt the buffer overflow:
int expand_stack(int n_bytes)
{
char buf[n_bytes];
return buf[n_bytes-1]; // access the memory to make sure the optimiser doesn't remove buf.
}
And in main, add a call to expand_stack before you call test:
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) &0xFFF);
int*space = (int*) alloca(offset);
*space = expand_stack(200);
test();
return 0;
}
Note that your code still invokes undefined behaviour.
Note2: If your compiler doesn't support variable length arrays, just use a fixed array, buf[200].
I want to write a parser for NBT (Named Binary Tags) structures. The format is represented like this:
TAG_Compound("hello world"): 1 entries
{
TAG_String("name"): Bananrama
}
And in memory (or the file it's stored in) as hexadecimal view:
0000000: 0a 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64 08 00 ...hello world..
0000010: 04 6e 61 6d 65 00 09 42 61 6e 61 6e 72 61 6d 61 .name..Bananrama
0000020: 00 .
0x0a = TAG_Compound
0x00 0x0b = name is 11 characters long
"hello world"
0x08 = TAG_String
0x00 0x04 = name is 4 characters long
"name"
0x00 0x09 = payload is 9 characters
"Bananarama"
0x00 = TAG_End
It can get more complicated with more and more nested TAG_Compounds like a tree structure.
Now my question is not exactly about parsing the format, it's really easy. I would rather like to know how I could efficiently and more importantly convenietly store it for later usage.
I know I can't obtain a degree of ease like
tags["hello world"]["name"] = "Bananrama"
But what's the best way to store it while keeping it easy to use? I thought about a nbt_compound structure (because every NBT tree has at least one root compound), have it store how many children it has and contain an array of nbt_value structs that would store the type and content of that value. Is that a good idea?
Edit: The full specification can be seen here
I am certain this code is broken, but the idea is what I am trying to convey. I think I would use a Tag object, like
struct TagHeader
{
TagType type; // Enum of COMPOUND, STRING, etc
char *name;
}
struct TagCompound
{
TagHeader header;
int nelems;
void *children;
}
struct TagString
{
TagHeader hearder;
char *value;
}
With a function, like
void *get_value(void *root, char *name)
{
int i;
if (! root) return NULL;
if (((TagHeader *) root)->type == COMPOUND)
{
TagCompound *c = (TagCompound *)root;
for (i = 0; i < c->nelems; i++)
{
if (strcmp(((TagHeader *) c->values[i])->name, name) == 0)
{
return c->values[i];
}
}
return NULL;
} else if ( /* handle other tag Types */ ) {
}
return NULL;
}
Then access it like:
get_value(get_value(root, "Hello World"), "name");