Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Win32 / MFC support #264

Open
maaarghk opened this issue Jul 1, 2024 · 2 comments
Open

Win32 / MFC support #264

maaarghk opened this issue Jul 1, 2024 · 2 comments

Comments

@maaarghk
Copy link

maaarghk commented Jul 1, 2024

I'm playing about with ImHex as a tool to reverse a program written using MFC which stores files using CArchive. There is a very useful post about this here.

I've written some structs that I think would probably be quite useful to add to the library, since MFC is obviously a very widely used tool and a lot of applications out there will use CArchive to store files.

Here's an example for strings.

struct MFCString {
    u8 length;
    if (length < 255) {
        char data[length];
    } else if (length == 255) {
        u16 nextLength;
        if (nextLength == 65535) {
            u32 maxLength;
            char data[maxLength];
        } else {
            char data[nextLength];
        }
    }
} [[sealed, format("std::string::impl::format_string"), transform("std::string::impl::format_string")]];

and for OleDateTime...

enum MFCOleDateTimeStatus : u32 {
    VALID = 0x00,
    INVALID = 0x01,
    NULL = 0x02
};

struct MFCOleDateTime {
    MFCOleDateTimeStatus status;
    double timestamp;
} [[sealed, format("formatOleTime")]];

fn transformOleTime(MFCOleDateTime oleDT)
{
    return std::time::to_utc((oleDT.timestamp - 25569.0) * 24.0 * 3600.0);
};

fn formatOleTime(MFCOleDateTime oleDT)
{
    std::time::Time newTime = transformOleTime(oleDT);
    return std::time::format(newTime);
};

I'm happy to contribute using MRs but wasn't sure where to put these organisationally. My gut says that std::string::MFCString and std::time::MFCOleDateTime are heading in the direction of polluting every single file with MFC stuff, although I see DOSTime sort of works like that.

Maybe a good option would be for you to add the above yourself in a place you see fit, and if/when I have more to contribute, I'll follow along with your organisational choices?

@WerWolv
Copy link
Owner

WerWolv commented Jul 1, 2024

Hey, thank you very much! These can absolutely just be added to the string and time library without issue. Everything in the standard library is in its own namespace either way and will not pollute any user code. I can add them to the relevant files if you want me to

@maaarghk
Copy link
Author

maaarghk commented Jul 1, 2024

I've taken a look but I think it'd be best if you add these ones and I just copy-by-example if/when I write any other implementations. Wasn't sure what to do about tests - I'm working with a proprietary app and don't have any files / patterns I can share to test it, given a bit more time I'm sure I could find that some core windows app is written using MFC and find a public domain pattern and file to add... in the mean time maybe this is helpful?

import std.time;
import std.string;

/**
    A serialised MFC CString
**/
struct MFCString {
    // Ref: https://github.com/adzm/atlmfc/blob/ea3ab8e4dee965905ae14f34d04b44ad1027827b/src/mfc/arccore.cpp#L28
    // TODO - support unicode strings / 8 byte lengths?
    u8 length;
    if (length < 255) {
        char data[length];
    } else if (length == 255) {
        u16 nextLength;
        if (nextLength == 65535) {
            u32 maxLength;
            char data[maxLength];
        } else {
            char data[nextLength];
        }
    }
} [[sealed, format("std::string::impl::format_string"), transform("std::string::impl::format_string")]];

enum MFCOleDateTimeStatus : u32 {
    VALID = 0x00,
    INVALID = 0x01,
    NULL = 0x02
};

/**
    A serialised MFC COleDateTime
**/
struct MFCOleDateTime {
    MFCOleDateTimeStatus status;
    double timestamp;
} [[sealed, format("format_ole_time")]];

/**
    Convert a serialised MFC COleDateTime to a UTC time
**/
fn ole_time_to_utc(MFCOleDateTime ole_dt)
{
    return std::time::to_utc((ole_dt.timestamp - 25569.0) * 24.0 * 3600.0);
};

fn format_ole_time(MFCOleDateTime ole_dt)
{
    std::time::Time time = ole_time_to_utc(ole_dt);
    return std::time::format(time);
};


struct MFCDoc {
    MFCString stuff;
    MFCOleDateTime stuff2;
    MFCString stuff3;
    MFCOleDateTime stuff4;
};

MFCDoc doc @0x00;

The following bytes (de-64 obv):

BlJhdGUgMQAAAACrqqqqYszmQP8qAWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6YWJjZGVmZ2hpamtsbW5vcHFyc
3R1dnd4eXoxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3
h5ejEyMzQ1Njc4OTBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkwYWJjZGVmZ2hpamtsbW5vcHF
yc3R1dgoNCg1hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d2N5ejEyMzQ1Njc4OTAgYWJjZGVmZ2QNCjAxMjM0NTY3ODkw
LT0rX2FiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6YWJjZGVmZ2hpamtsbW5vcHFyc3R1DQoAAAAAimdFIzXP5UA=

should result in this output

{
    "doc": {
        "stuff": "Rate%201",
        "stuff2": "Sun%20Oct%2031%2002%3A00%3A00%202027",
        "stuff3": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuv%0A%0D%0A%0Dabcdefghijklmnopqrstuvwcyz1234567890%20abcdefgd%0D%0A01234567890-%3D%2B_abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu%0D%0A",
        "stuff4": "Thu%20Apr%2014%2015%3A51%3A12%202022"
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants