working on my reversing skillset here and I came upon something I thought i understood but I managed to confuse myself.
Working in C mainly
My function returns me an address for the information I want to access.
LRESULT ret = SendMessage(hComboBox, CB_GETITEMDATA, (WPARAM)0 , (LPARAM) 0);
// the exact function doesn't really matter here.
printf("Address: %p\n", ret); // Output is 09437DF8
A dump of this address results in
09437DF8 A0 55 E8 12
This is the address (note endianness) of the data I really want to read.
12e855A0
12 E8 55 A0 - 30 00 3A 00 30 00 33 00 3A 00 32 00 32 00 00 00 - UNICODE "0:03:22"
Now I'm fairly certain this is just basic pointers/referencing/de-referencing but i cant wrap my head what I have to do to read this value pragmatically.
wprintf(L"%s\n", <value at address pointed to by ret>);
// Yes its a null terminated string
// Im working via injected dll, so no access violations
// string is unicode
Perhaps something like this?
#include <stdio.h>
#include <wchar.h>
int main()
{
wchar_t *name = L"UNICODE String";
void **ret = (void **)&name;
wprintf(L"%ls \n", *(wchar_t **)ret);
return 0;
}
Related
Following is my code. In this program I use system function and passe a command line argument to get the mac address of the pc and then write it into the txt file. txt file is creating successfully. But When I try to open the txt file which was created it wont show anything. It show letter M and some blank spaces. Any idea why is this happening ? Thank you.
#include<stdio.h>
int main()
{
system("wmic nic where (AdapterTypeId=0 AND netConnectionStatus=2) get MACAddress >macaddress.txt");
FILE * fpointer=fopen("macaddress.txt","r");
char buffer[500];
while(!feof(fpointer)){
fgets(buffer,500,fpointer);
puts(buffer);
}
fclose(fpointer);
}
This will do what you want, but if instead of just printing the contents of the file you actually want to do something with it and you need the text as ASCII you'll need to perform that conversion yourself from wide characters.
Since this particular file is just normal letters and numbers text you can convert the wide string to narrow with sprintf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
system("wmic nic where (AdapterTypeId=0 AND netConnectionStatus=2) get MACAddress > macaddress.txt");
//Binary mode tells fgetws to read wide characters instead of multi-byte.
FILE * fp = fopen("macaddress.txt", "rb");
if (fp)
{
wchar_t buffer[500] = { 0 };
fread(buffer, 1, 2, fp); //read and discard BOM
while (fgetws(buffer, 500, fp))
{
// %ls means the parameter is a wide string.
// %S also works in Visual Studio
printf("%ls", buffer);
//Convert wide characters to ASCII
//This assumes the wide characters are all in the ASCII range
char ascii[500] = { 0 };
sprintf(ascii, "%ls", buffer);
printf("%s", ascii);
}
fclose(fp);
}
return 0;
}
It is not an ASCII encoded file. Here is a dump
0 1 2 3 4 5 6 7 8 9 A B C D E F
0000:0000 FF FE 4D 00 41 00 43 00 41 00 64 00 64 00 72 00 ■M.A.C.A.d.d.r.
0000:0010 65 00 73 00 73 00 20 00 20 00 20 00 20 00 20 00 e.s.s. . . . . .
0000:0020 20 00 20 00 20 00 20 00 0D 00 0A 00
etc so as not to reveal my MAC address.
Note too it contains zeros which will terminate any string output after reading with fgets.
My text editor (Notepad++) shows the correct content because it sets the right text format automatically.
I cannot get my input character value properly. Here is my code:
#include <stdlib.h>
void main()
{
char buf_in[32] = { 0 };
printf("input: ");
gets_s(buf_in, 32);
for (int i = 0; i < 32; i++)
printf("%02x ", buf_in[i]);
getchar();
}
I input the character by <alt-254>, but the result is 74 00 00 ..., not fe 00 00 ....
Here is my local environment: chcp 936.
And I test in some different local environments (ANSI code page 936):
1. OEM code page 936 result : 74 00 00 ...
2. OEM code page 65001 result : 00 00 00 ... (weird)
3. OEM code page 1250 result : 3f 00 00 ...
4. OEM code page 437 result : 5f 00 00 ...
I think ALT-codes are not supported by windows console. Please look here:
Alt Codes in Batch
You can try to put ALT-code (or any other data...) in file and then redirect input to Your program:
./prog.exe < input.txt
To be sure that you put proper value in file i suggest to use hex editor (like XVI32)
Does it work for other characters?
This question already has answers here:
printf adds extra `FFFFFF` to hex print from a char array [duplicate]
(3 answers)
Closed 7 years ago.
printf() function prints leading ffffff (technically I understand that most significant bit carries sign so it gets carried all the way to where data starts). But how to get rid of them I have no idea and why is it happening?
int mem_display(Cmd *cp, char *arguments)
{
int i;
char *adr;
if (!sscanf(arguments,"%x",&adr))
{
return 0;
}
printf("%#0.8s ",arguments);
for (i=0; i<16; i++) {
printf("%02.x ",(unsigned int)*(adr+i));
}
...
the output:
% UNIX> md 10668
/*calling function show memory location 0x10668*/
OUT:
10668 ffffffbc 10 20 ffffffe0 ffffffa0 40 ffffffa2 ffffffa0 44 ffffff9c 23 ffffffa0 20
solved:
printf("%0.2x ",(unsigned int)*(adr+i));
output:
UNIX> md 10000
10000 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00 .ELF............
Cast to unsigned char to have the system consider *(adr+i) as unsigned, so that no sign expansion will be done.
for (i=0; i<16; i++) {
printf("%02.x ",(unsigned char)*(adr+i));
}
Please read the printf() manual, this is the correct way
printf("%02x ", (unsigned char) adr[i]);
Note: don't use this *(a + i) notation, and specially when you are casting it. It's not a bad way to dereference a pointer, it's just not appropriate in this particular situation.
When I first run I would add 3 records, which gives me a count of 3. Then I fwrite the count into a bin file, and the records into a bin file, then I close the program.
When I reopen it and then I fread in and it will give me my 3 records and a count of 3. But from there on, no matter if I back up or when I read in, it will give me the same count 3 and 3 records, though since the count isn't being updated either this may be why fread is only reading in the first time records.
I am not sure why the counter isn't updating. Both fread and fwrite are returning = success so I am not sure what`s up.
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\\myFiles\\counter.bin", "a+b");
if (result1 == 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
printf("Back up of counter failed! error:%d",result1);
FILE *record;
errno_t result2 = fopen_s(&record, "c:\\myFiles\\record.bin", "a+b");
if (result2 == 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
printf("Back up of record failed! error:%d", result2);
}
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\\myFiles\\counter.bin", "a+b");
if (result1 == 0){
result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
printf("Counter:%d", *pCounter);
}
else
printf("Upload up of counter failed!");
FILE *record;
errno_t result2 = fopen_s(&record, "c:\\myFiles\\record.bin", "r+b");
if (result2 == 0)
{
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
printf("Upload successful!\n");
fclose(record);
}
else
printf("Error opening file!");
}
Transferring the most salient comments into an answer.
Weathervane commented:
How do you know that fread and fwrite are returning "success" when you have not checked their return value?
Jude commented:
I look through the debugger and step in to the function, result is giving me their success return values (if that's how it works).
Weathervane commented:
You still need that in the program. Without that sort of checking, your code will be blown over by a puff of wind.
Dmitri correctly observed:
Looks like everywhere you open in append mode "a+b" you should probably be using something else ("rb" in upload() and "wb" in backUp() possibly?)
Jude commented:
I don't understand, is there a specific function for error checking? As I had always thought that error checking was just looking at what goes in the value of result and then I can go check what the value means?
Look at the specification of fread() and
fwrite(). They return the number of records written or read, which may be less than the number requested. If you get a short write, then you have a problem — maybe out of disk space. If you get a short read, it may be that you requested 100 records but there were only 1 or 10 or 99 available to read (or there was an error). If you don't capture and check the return value, you've no idea what happened.
Jude commented:
I see they read and write 1, but it still stores the first 3 elements of my struct array. I assume it's one because it's only writing my array?
fread() (and fwrite() too) give you considerable flexibility because you can supply the size of an item and the number of items separately. You use:
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
This tells fread() to read 1 item of size *pCounter * sizeof(PAYROLL). You will get a result of 1 (success) or 0 (failure). You could have specified:
result2 = fread(employee, sizeof(PAYROLL), *pCounter, record);
which would tell you how many records of size sizeof(PAYROLL) were read, up to a maximum of the value in *pCounter. You might get 0 or 1 or …
Here is some workable code that does more or less what's required. The main() program demonstrates working with 1, 2 and 3 records (and the names are a few kings and queens of England, along with the year of their ascension to the throne as their employee ID number). I had to create a minimal payroll structure since the question didn't provide one.
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct PAYROLL
{
long emp_id;
char emp_name[32];
} PAYROLL;
static const char counter_bin[] = "counter.bin";
static const char records_bin[] = "records.bin";
static
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "wb");
if (counter != 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
fprintf(stderr, "Back up of counter failed! error: %d %s\n", errno, strerror(errno));
FILE *record = fopen(records_bin, "wb");
if (record != 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
fprintf(stderr, "Back up of records failed! error: %d %s\n", errno, strerror(errno));
}
static
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "rb");
if (counter != 0){
size_t result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
if (result != 0)
printf("Counter: %ld\n", *pCounter);
else
fprintf(stderr, "Failed to read counter\n");
}
else
fprintf(stderr, "Upload up of counter failed!\n");
FILE *record = fopen(records_bin, "r+b");
if (record != 0)
{
size_t result2 = fread(employee, *pCounter * sizeof(PAYROLL), 1, record);
if (result2 == 1)
printf("Upload successful!\n");
else
fprintf(stderr, "Failed to read records!\n");
fclose(record);
}
else
fprintf(stderr, "Error opening file!");
}
int main(void)
{
PAYROLL emps[] =
{
{ 1066, "William the Conqueror" },
{ 1819, "Victoria" },
{ 1689, "William and Mary" },
};
for (int i = 1; i <= 3; i++)
{
long emp_count = i;
printf("Employee count = %ld\n", emp_count);
backUp(emps, &emp_count);
upload(emps, &emp_count);
for (int j = 0; j < emp_count; j++)
printf("%4ld: %s\n", emps[j].emp_id, emps[j].emp_name);
}
return 0;
}
Note that I've factored out the file names so that you only have to change a single line to change the files used. Sample output:
$ Employee count = 1
Counter: 1
Upload successful!
1066: William the Conqueror
Employee count = 2
Counter: 2
Upload successful!
1066: William the Conqueror
1819: Victoria
Employee count = 3
Counter: 3
Upload successful!
1066: William the Conqueror
1819: Victoria
1689: William and Mary
$ odx counter.bin
0x0000: 03 00 00 00 00 00 00 00 ........
0x0008:
$ odx records.bin
0x0000: 2A 04 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 *.......William
0x0010: 74 68 65 20 43 6F 6E 71 75 65 72 6F 72 00 00 00 the Conqueror...
0x0020: 00 00 00 00 00 00 00 00 1B 07 00 00 00 00 00 00 ................
0x0030: 56 69 63 74 6F 72 69 61 00 00 00 00 00 00 00 00 Victoria........
0x0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0050: 99 06 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 ........William
0x0060: 61 6E 64 20 4D 61 72 79 00 00 00 00 00 00 00 00 and Mary........
0x0070: 00 00 00 00 00 00 00 00 ........
0x0078:
$
(odx is just a hex dump program. Pick your own program that does an equivalent job — od -c is a fallback, though I don't particularly like its formatting.)
I see many faults in your program.
Firstly, you are writing long ints and PAYROLL structures directly to a file. You should never do that, as structures and integers have a machine-dependent representation and if you write the files on one machine (let's say 32-bit machine) and read them on another machine (let's say 64-bit machine) then you might run into problems.
Secondly, you're not checking the return value of fread(). It should be always checked.
Thirdly, you're assigning the return value of fread() to an errno_t. Are you sure you really want to do that?
If you want to have the answer to the actual problem, consider updating the source code to fix the mistakes I pointed out and consider improving the English language in your question. Furthermore, you should provide a complete example, i.e. one that contains the definition of PAYROLL. When you know the actual return value of fread(), perhaps the problem will be easier to track down then.
I am missing a fundamental point on passing values.
In my code, I wrote this prototype/function:
void drawFont (char A[],unsigned char length, char x1, char y1, uint16 FGcolor);
I call the function using a call like this:
drawFont ("William",7,15,25,YEL,0);
or
drawFont ("W",1,15,25,YEL,0);
Both of these work fine in the code. If I examine A[0] in the function, I will see a value of '57' representing an ASCII 'W'. All fine and good.
My question/problem is: When I attempt to replicate the 'W' using the ASCII value instead of the string representation, my code fails Example:
drawFont (57,1,15,25,YEL,0);
The value of A[0] in the code is: 0, but the address of A is 57. So somehow the compiler assumes that I want to pass a pointer? I'm confused, why did it pass the string fine, but not the value?
Thanks in advance from a novice C programmer.
If you pass
drawFont (57,1,15,25,YEL,0);
you will be doming the same as
drawFont ('W',1,15,25,YEL,0);
which is just one character. The function requires an array of characters, that's why it's not correct.
The prototype for your function declares that the first parameter is a pointer to a character:
void drawFont (char A[],...);
If you pass an integer, you are breaking the rules. The compiler should warn about it. Mine gives a warning about the following code on the line with func(57):
void func(char a[])
{
}
char arr[] = {87,84,70};
int main()
{
func(57);
func("W");
func(arr);
}
x.c(9) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int'
x.c(9) : warning C4024: 'func' : different types for formal and actual parameter 1
If you look at the assembly output from the compiler, you can see the problem more clearly (I cut out the uninteresting parts):
PUBLIC _arr
_DATA SEGMENT
_arr DB 057H ;Here's the char array at an address in memory.
DB 054H
DB 046H
ORG $+1
$SG1297 DB 'W', 00H ;Here's the "W" at an address in memory (nul-terminated)
_DATA ENDS
; 9 : func(57);
00003 6a 39 push 57 ; Push 57 as the address, WRONG!
00005 e8 00 00 00 00 call _func
0000a 83 c4 04 add esp, 4
; 10 : func("W");
0000d 68 00 00 00 00 push OFFSET $SG1297 ; Push the address of the string.
00012 e8 00 00 00 00 call _func
00017 83 c4 04 add esp, 4
; 11 : func(arr);
0001a 68 00 00 00 00 push OFFSET _arr ; Push the address of the array.
0001f e8 00 00 00 00 call _func
00024 83 c4 04 add esp, 4
The code is expecting to go to an address to read characters. Who knows what is in address 57.
The value of A[] is actually a pointer, such as &A[0] (you could rewrite the function using char *A instead of char A[]
That is the address of the first slot, not what is stored in it. In the memory location pointed to by the pointer, there exists a value 57. When you write a function with a char array or char pointer parameter, you tell the compiler: I will pass you a memory address. Go to that address and start reading each char (number) until you arrive at the null byte, then stop.
But when you pass literal integer 57 as the argument, that is not a valid pointer to an array of characters. You are missing the level of indirection.
So lets assume your char A[] resides at 0xfeaa0011
In RAM at 0xfeaa0011 -> "William" (or 52, ...)
The correct call to drawFont() actually looks like drawFont(0xfeaa0011, 1, 15, 25, YEL, 0)
So you see replacing the pointer with 57 isn't the same thing.
Your function requires a string ( char[] ) as an argument.
When you pass "William" it is interpreted as a string, that's normal.
When you pass "W" it is also interpreted as a string:
string[2] = { 'W' + 0 } //notice the null byte following your char
That's because you used double-quotes " instead of single-quotes '.
Therefore passing 57 or 'W' is viewed as a single char and not a char[]/string which then gives you an error since your function is expecting a char[] and you gave it a char.