3

I have an unsigned char array unsigned char* name = malloc(nameLength); - how can I print it with printf? %sdoes not seem to work correctly, neither does %u (seeing random icons).

Here's how I create the data I want to print:

__int32 nameLength;
ReadProcessMemory(hProcess, (LPCVOID)(classNamePtr + 0x0004), &nameLength, sizeof(__int32), 0); //Reads nameLength to be 13 in this case
unsigned char* name = malloc(nameLength+5); //Add 5 for good measure, it is null terminated
ReadProcessMemory(hProcess, (LPCVOID)(nameStrPtr), name, nameLength, 0);
name[nameLength] = 0; //null terminate

printf("%s", name); //Outputs single character strange characters, like an up icon
Christian Stewart
  • 15,217
  • 20
  • 82
  • 139
  • If `name` contained a null-terminated string of printable characters, then the `printf` format `%s` would work. That's what it's for. What's in the array, just arbitrary numbers? Can you share a little more? – lurker Jan 03 '14 at 20:34
  • You haven't given us enough information. Read http://sscce.org/ – Keith Thompson Jan 03 '14 at 20:35
  • I've added some more information @KeithThompson – Christian Stewart Jan 03 '14 at 20:36
  • If it null-terminated, %s should work. As you have spare space at the end, try manually writing a \0 there, and try again. – gnometorule Jan 03 '14 at 20:40
  • @gnometorule In the code I do that - `name[nameLength] = 0` – Christian Stewart Jan 03 '14 at 20:41
  • What did you expect to find in memory? Strange bytes that display little icons sounds about right to me. :) I certainly don't expect to see Shakespeare! – abelenky Jan 03 '14 at 20:43
  • Oh, I see. If it prints gibberish, loop over the chars, and print as %02x. – gnometorule Jan 03 '14 at 20:45
  • @abelenky I know what is in that spot (it's a target of a pointer) - If you're scanning memory, you can most certainly find shakespeare :) – Christian Stewart Jan 03 '14 at 20:48
  • Wiry newly added info, your program works as expected. The memory area you read from has values in the non-printable range. The best you can hope for is to print them as hex (or maybe decimals); or to accept as presented by %s. – gnometorule Jan 03 '14 at 20:53
  • You're using windows, which means that even if it was a valid string, it's actually a utf-16 string, so you want wprintf as well – Anya Shenanigans Jan 03 '14 at 21:01

1 Answers1

1

When one detects a non-printable char, output an escape sequence or hexadecimal value

#include <ctype.h>
#include <string.h>
#include <stdio.h>

int printf_ByteArray(const unsigned char *data, size_t len) {
  size_t i;
  int result = 0;
  for (i = 0; i < len; i++) {
    int y;
    int ch = data[i];
    static const char escapec[] = "\a\b\t\n\v\f\n\'\"\?\\";
    char *p = strchr(escapec, ch);
    if (p && ch) {
      static const char escapev[] = "abtnvfn\'\"\?\\";
      y = printf("\\%c", escapev[p - escapec]);
    } else if (isprint(ch)) {
      y = printf("%c", ch);
    } else {
      // If at end of array, assume _next_ potential character is a '0'.
      int nch = i >= (len - 1) ? '0' : data[i + 1];
      if (ch < 8 && (nch < '0' || nch > '7')) {
        y = printf("\\%o", ch);
      } else if (!isxdigit(nch)) {
        y = printf("\\x%X", ch);
      } else {
        y = printf("\\o%03o", ch);
      }
    }
    if (y == EOF)
      return EOF;
    result += y;
  }
  return result;
}

If data contained one of each byte, sample follows:

\0...\6\a\b\t\n\v\f\xD\xE\xF\x10...\x1F !\"#$%&\'()*+,-./0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7F...\xFE\o377

The selection of escape sequences will vary with code goals. The set above attempts to conform to something a C parser would accept.
Note: With the last else, always outputting a 3-digit octal sequence has scanning advantages, but folks are more accustomed to hexadecimal than octal.
Adjusted to conditionally print in hex depending on the following character.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256