Second Life Copybot

Full Version: C++ generate a random MAC?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Need a little help from someone who knows more C++ than I do.  Every source I have, that has anything about spoofing the hardware in it, generates a random hash based on the MAC address.  I want to go one level deeper and generate a random MAC itself, then base the hash on that generated MAC.  I do not know enough C++ to do it.  There are examples all over the web to do in a stand alone program, a random MAC address, but I don't know how to translate that into a snippet that will work inside this existing code.

What I am working with that needs to be different:

llfloaterspooflogin.cpp
Code:
void LLFloaterSpoof::onClickMACRandom(void* userData)
{
LLFloaterSpoof* panel = (LLFloaterSpoof*)userData;
unsigned char seed[16]; /* Flawfinder: ignore */
LLUUID::getNodeID(&seed[0]);
seed[6]='U';
seed[7]='W';
LLUUID::getSystemTime((uuid_time_t *)(&seed[8]));

char hash_string[MD5HEX_STR_SIZE];
LLMD5 hash;
hash.update( seed , 16 );
hash.finalize();
hash.hex_digest(hash_string);
gSavedSettings.setString("SpecifiedMAC",std::string(hash_string));
panel->fillMAC();
}

llviewerstats.cpp
Code:
unsigned char MACAddress[MAC_ADDRESS_BYTES];
LLUUID::getNodeID(MACAddress);
LLDate date;
std::string day = date.Day();
std::string month = date.Month();
std::string macAddressString = llformat("%02x-%02x-%02x-%02x-%02x-%02x", MACAddress[0], day, month, MACAddress[3], MACAddress[4], MACAddress[5]);
system["mac_address"] = macAddressString;


in these snippets, LLUUID::getNodeID() gets the actual MAC address, in the first one assigning it to a seed for the hash spoofing, and in the second one, using it as a basis for a random string to send with the viewer stats.  there are some problems with this as it stands.  one, is that the seed for the hash will change if your actual MAC changes.  not a big deal but i want my signature totally under user control.  another, is that the actual MAC sent in with the stats, even tho it's spoofed, does not produce the same hash that the above code sends as the spoofed hash.  also in my testing, the spoofed MAC string does not format properly.  and, as written, because it bases the MAC spoof on the date, it changes every day. so again, i want that under user control.

basically i would prefer to generate the spoofed MAC in the code in the spoof floater, base the hash on it, and save it and let the viewer stats use it, instead of the MAC spoofing being done in viewerstats.

anyone have any suggestions?
I use a completely hardware indipendent routine to generate MAC.
MAC is derived from a random UUID or calculate on known UUID.
In the first case the MAC is Random, in the second depend from the UUID i use;

Sorry it is C#.

Code:
................................
................................
string MAC = GetRandomMAC(myUUID);
................................
................................

// Return a random MAC if param = UUID zero
// or a fixed MAC calculated on UUID(if not zero)
public static string GetRandomMac(UUID seed)
{
    string lmac = string.Empty;
    if (seed == UUID.Zero)
        lmac = UUID.Random();
    else
        lmac = seed;
    string mac = lmac.ToString().Substring(24, 12);
    return String.Format("{0}:{1}:{2}:{3}:{4}:{5}",
               mac.Substring(0, 2),
               mac.Substring(2, 2),
               mac.Substring(4, 2),
               mac.Substring(6, 2),
               mac.Substring(8, 2),
               mac.Substring(10, 2));
}
Simple enough, once I got my head around it, that "random MAC" just really means "six random numbers 0-255 in hex".

Code:
void LLFloaterSpoof::onClickMACRandom(void* userData)
{
LLFloaterSpoof* panel = (LLFloaterSpoof*)userData;

unsigned char MACspoof[MAC_ADDRESS_BYTES];
for (int i = 0; i < MAC_ADDRESS_BYTES; i++) {
MACspoof[i] = ll_rand(255);
}

std::string macSpoofString = llformat("%02x-%02x-%02x-%02x-%02x-%02x",
MACspoof[0], MACspoof[1], MACspoof[2], MACspoof[3], MACspoof[4], MACspoof[5]);

char hash_string[MD5HEX_STR_SIZE];
LLMD5 hash;
hash.update( MACspoof , MAC_ADDRESS_BYTES );
hash.finalize();
hash.hex_digest(hash_string);

gSavedSettings.setString("SpecifiedMAC",macSpoofString);
gSavedSettings.setString("SpecifiedMAChash",std::string(hash_string));

panel->fillMAC();
}


And now that i have this, llviewerstats just picks up the saved setting.  For the purists among us, which I count myself included, this does not take into account any of the official stuff about MAC address specifications, like vendor identification, unicast vs multicast, local vs global administration.  But I am not writing two pages of code to do all that; anyone that picky, or me, can go look up on the web a "real" MAC address and type it in lol.  This is only used for viewer identification, and is never involved in any actual traffic control or routing information.

I'm also considering whether to write in some code in which if the user wishes, to re-hash the saved passwords against the specified hardware ID's.  In effect it would make the viewer at that time react the same way as if the network card had actually been changed, and you would need to re-enter all passwords.  But on the other side of the same coin, if I made the option available, you -could- change your network however much you like, and because your passwords are hashed against your own saved info instead of the actual hardware, you would never have to do that again, as long as your saved info remained intact.  

One risk I can think of though is that it would also allow to spoof another machine's hardware, and if an unscrupulous user had access to a machine on which they could get someone else's hardware info and -their- saved passwords file, they could use that copied to their computer and steal all of whatever accounts were in that file.  That's possible anyway, given enough time to do it with other software;  I just don't know really how to weigh the risk of making it available contained within the viewer.  Any input is welcome; for the time being I'm not doing it, and I may make a separate thread about it later.
This is a old threat but I wanted to submit my rookie-approach on the latest FireStorm viewer:

./src/phoenix-firestorm/indra/newview/llappviewerlinux.cpp
Code:
std::string LLAppViewerLinux::generateSerialNumber()
{
    char serial_md5[MD5HEX_STR_SIZE];
    serial_md5[0] = 0;

    //Generate Random UUID (Volume Serial)
    std::string best = LLUUID::generateNewID().asString();

    // we don't return the actual serial number, just a hash of it.
    LLMD5 md5( reinterpret_cast<const unsigned char*>(best.c_str()) );
    md5.hex_digest(serial_md5);

    return serial_md5;
}

./src/phoenix-firestorm/indra/llcommon/lluuid.cpp
Code:
S32 LLUUID::getNodeID(unsigned char *node_id)
{
    char MACAddress[6];

    //Generate Random MAC Address
    get_random_bytes(MACAddress, 6);

    memcpy(node_id, MACAddress, 6);
    return 1;
}

The solution works but I'm unsure how to save these values per user-account. So they can persist and provide consistent login values for the viewer.
Bios Serial Spoofer

File: ./indra/newview/llmachineid.cpp
Code:
Code:
S32 LLMachineID::init()

{

    size_t len = sizeof(static_unique_id);

    memset(static_unique_id, 0, len);

    S32 ret_code = 0;



    unsigned char * staticPtr = (unsigned char *)(&static_unique_id[0]);

    ret_code = LLUUID::getNodeID(staticPtr);

    has_static_unique_id = true;



    LL_INFOS("AppInit") << "UniqueID: 0x";



    // Code between here and LL_ENDL is not executed unless the LL_DEBUGS

    // actually produces output

    for (size_t i = 0; i < len; ++i)

    {

        // Copy each char to unsigned int to hexify. Sending an unsigned

        // char to a std::ostream tries to represent it as a char, not

        // what we want here.

        unsigned byte = static_unique_id[i];

        LL_CONT << std::hex << std::setw(2) << std::setfill('0') << byte;

    }

    // Reset default output formatting to avoid nasty surprises!

    LL_CONT << std::dec << std::setw(0) << std::setfill(' ') << LL_ENDL;



    return ret_code;

}

It seems the Windows viewer uses BIOS Serial number instead of the MAC Address, replace S32 LLMachineID::init() with this code, to eliminate the BIOS checking functionality. So I'm adding this code besides the Mac Address Spoofer and Volume Serial Spoofer.