Search code examples
windowswinapixorwidechar

Converting hex to bytes using the win32 API wide string - matasano challenge #2


I've started doing the matasano challenges and decided to do it with just the C PL and the win32 API.

I want to do it this way since I want to get very familiar with the win32 API and the obfuscation/encryption techniques malware authors would use.

I've noticed that the second challenge will require me to use the wide string version of the CryptStringToBinary (=CryptStringToBinaryW) since I can't properly decode the first hex string properly (only 3 characters properly decoded as opposed to the 18 characters in the second given hex string).

Here's the link to the challenge: https://cryptopals.com/sets/1/challenges/2

I've been really struggling for the past few hours trying to convert this to the wide string version but I could not get it to work at all, here's my current code (which works great for the ANSI):

LPSTR ToBinary(BYTE* test, LPSTR buffer, DWORD amount) {
if (CryptStringToBinaryA(test, strlen(test), CRYPT_STRING_HEXRAW, NULL, &amount, NULL, NULL))
{
    buffer = malloc(amount + 1);
    memset(buffer, 0, amount + 1);
    if (buffer == NULL)
    {
        printf("failed, error: %lu", GetLastError());
        return NULL;
    }
    if (CryptStringToBinaryA(test, strlen(test), CRYPT_STRING_HEXRAW, buffer, &amount, NULL, NULL))
    {
        printf("%s \n", buffer);
    }
}
else
    printf("failed, error: %lu", GetLastError());

return buffer;


 }


int main(void)
{
    BYTE * test = "1c0111001f010100061a024b53535009181c";
    LPSTR first = NULL;
    DWORD amount = 0;
    first = ToBinary(test, first, amount);


    LPSTR buffer2 = NULL;
    BYTE* test2 = "686974207468652062756c6c277320657965";
    amount = 0;
    LPSTR second = NULL;
    second = ToBinary(test2, second, amount);



    return 0;
}

My question is:

How do I convert this into the wide string version?

I've tried replacing all the LPSTR with LPWSTR, strlen to wsclen and use the "reinterpret casting" to convert from LPWSTR to BYTE* as required by the winAPI documentation. (like this: foo = (BYTE*)test; when test is of type LPCWSTR).

but after all my changes, my program doesn't work anymore.

I'm quite the beginner in C programming and I'm probably missing the correct "attitude" for these kind of conversion problems, I hope this is not a direct duplicate to another question.

Edit:

I've tried this code but when I check the strlen of the first value, it returns a length of 3 rather than 18 on the second hex string:

length is: 3

hit the bull's eye

length is: 18


Here's the code I tried:

BYTE* ToBinary(LPCWSTR test, BYTE* buffer, DWORD amount) {
    if (CryptStringToBinaryW(test, wcslen(test), CRYPT_STRING_HEXRAW, NULL, &amount, NULL, NULL))
    {
        buffer = malloc(amount + 1);
        memset(buffer, 0, amount + 1);
        if (buffer == NULL)
        {
            printf("failed, error: %lu", GetLastError());
            return NULL;
        }
        if (CryptStringToBinaryW(test, wcslen(test), CRYPT_STRING_HEXRAW, buffer, &amount, NULL, NULL))
        {
            return buffer;
        }
    }
    printf("failed, error: %lu", GetLastError());
    return 0;
}


int main(void)
{
    LPCWSTR test = L"1c0111001f010100061a024b53535009181c";
    BYTE* first = NULL;
    DWORD amount = 0;
    first = ToBinary(test, first, amount);
    printf("%hS\n", first);
    printf("length is: %d\n", strlen(first));

    LPCWSTR test2 = L"686974207468652062756c6c277320657965";
    amount = 0;
    BYTE* second = NULL;
    second = ToBinary(test2, second, amount);
    printf("%hS\n", second);
    printf("length is: %d\n", strlen(second));

    return 0;
}

Solution

  • I've tried this code but when I check the strlen of the first value, it returns a length of 3 rather than 18 on the second hex string:

    The length of a C string is determined by the terminating null-character: A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).

    So the reason is the fourth character of first is a terminating null character ('\0') cause strlen stop and return 3.