> For the complete documentation index, see [llms.txt](https://mapol.gitbook.io/home/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mapol.gitbook.io/home/blog/malware-analysis/stealer/svcstealer.md).

# SvcStealer

Jan 30, 2026

According to the reports from [**Cyfirma**](https://www.cyfirma.com/news/weekly-intelligence-report-28-mar-2025/), [**ANY.RUN**](https://any.run/malware-trends/svcstealer/), and [**Seqrite**](https://www.seqrite.com/blog/svc-new-stealer-on-the-horizon/), the stealer was discovered around January, 2025. It was designed to target a wide range of credentials, with a primary focus on both individual users and businesses.

I found this sample on: [**MalwareBazaar.**](https://bazaar.abuse.ch/sample/d2f1a8cbd4f6e007d3bde6996d15c915be6081e1ab2d5290f5f50c9fe1b9cc27/)

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*VHmNy0lU3_Ly77Czq8I6cw.png" alt="" height="389" width="700"><figcaption><p><a href="https://any.run/malware-trends/svcstealer/">ANY.RUN - SVCStealer</a></p></figcaption></figure>

***

### Table of Contents <a href="#f1cf" id="f1cf"></a>

1. [Sample Overview](#id-911c)
2. [Execution Guardrails: Mutual Exclusion (T1480.002)](#d38b)
3. [Initial Indicator Removal: File Deletion (T1070.004)](#id-3520)
4. [Obfuscated Files or Information: Dynamic API Resolution (T1027.007)](#dcc9)
5. [Debugger Evasion (T1622)](#c0b4)
6. [Data Staged: Local Data Staging (T1074.001)](#id-482f)
7. [Impair Defenses: Disable or Modify Tools (T1562.001)](#a17c)
8. [Credentials from Password Stores: Credentials from Web Browsers (T1555.003)](#b6fb)
9. [Unsecured Credentials: Credentials In Files (T1552.001)](#dfbd)
10. [Initial Screen Capture (T1113)](#b204)
11. [Software Discovery (T1518)](#id-8465)
12. [System Information Discovery (T1082)](#id-0c17)
13. [Process Discovery (T1057)](#id-20ba)
14. [Browser Information Discovery (T1217)](#id-3752)
15. [Archive Collected Data (T1560)](#eb7e)
16. [Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted Non-C2 Protocol (T1048.003)](#f435)
17. [Final Indicator Removal: File Deletion (T1070.004)](#final-indicator-removal-file-deletion-t1070.004)
18. [System Owner/User Discovery (T1033)](#id-4e89)
19. [Final Screen Capture (T1113)](#final-screen-capture-t1113)
20. [Execution Flow](#e28a)
21. [Conclusion](#id-5ae9)
22. [IOCs](#id-36f6)
23. [YARA Rule](#ac92)
24. [Sigma Rule](#f3ca)
25. [Additional Resources](#id-8d83)

***

### Sample Overview <a href="#id-911c" id="id-911c"></a>

The sample was written in C++ and was compiled around December 23, 2025, using Microsoft Visual Studio 2022. Also, the sample selected for analysis does not apply any packing method.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*eEw7HAKKMiVzZan6bQEtHw.png" alt="" width="563"><figcaption><p>Figure 1. Identified the compile time and languages used by the sample.</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*4EZ0YqVK7W4aY-nsFpDoxg.png" alt="" width="563"><figcaption><p>Figure 2. The entropy values of a sample.</p></figcaption></figure>

***

### Execution Guardrails: Mutual Exclusion (T1480.002) <a href="#d38b" id="d38b"></a>

At the very beginning, a mutex is created with the name `build_cvbfihjudpnetx`. However, if this mutex already exists, the process will exit.

<figure><img src="https://miro.medium.com/v2/resize:fit:605/1*_7vmISNuo4Eyey_aHmMSxQ.png" alt="" height="127" width="484"><figcaption><p>Figure 3. Create and check if the mutex already exists.</p></figcaption></figure>

***

### Initial Indicator Removal: File Deletion (T1070.004) <a href="#id-3520" id="id-3520"></a>

Inside `sub_1400DBBE0` function, it calls `GetCurrentHwProfileW` to retrieve information about the current hardware profile of the local computer, and store it in `HwProfileInfo`. However, before this call, the `memset` function is used to set the first 244 bytes of the pointed memory block to zero in this case, `HwProfileInfo`.

This may have been done intentionally to wipe the buffer before storing the retrieved information.

<figure><img src="https://miro.medium.com/v2/resize:fit:729/1*QzOS7BmbypolkKlLGkOM3A.png" alt="" width="563"><figcaption><p>Figure 4. Retrieve the current hardware information.</p></figcaption></figure>

As the loop began, it started retrieving the `GUID`, which can be identified by the arrays start index being set to four. This indicates that the first four bytes are skipped. According to the `HW_PROFILE_INFOW` structure, the first four bytes represent the `DWORD dwDockInfo`, followed by `szHwProfileGuid`.

This means that the current index position will now points to the `szHwProfileGuid`, as shown in Figure 6.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*cl-gwDMLMT6vqZwdVkfuAw.png" alt="" height="112" width="700"><figcaption><p>Figure 5. Skip the first four byte for GUID field.</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*T3eSILW2tjEW6CggaClydA.png" alt="" height="136" width="700"><figcaption><p>Figure 6. HW_PROFILE_INFOW structure.</p></figcaption></figure>

After that, the function `SHGetFolderPathW` is called. An interesting argument is `35`, which represent to `CSIDL_COMMON_APPDATA`.

<figure><img src="https://miro.medium.com/v2/resize:fit:715/1*7f0eYgkGBWCs_wevt1nKLg.png" alt="" width="563"><figcaption><p>Figure 7. Retrieve the current AppData folder.</p></figcaption></figure>

Now, when the function returns, its value is a concatenation of the `ProgramData` directory and the machines `GUID`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*o_RcJLfMAAoLiI3sPPVxpQ.png" alt="" height="114" width="700"><figcaption><p>Figure 8. Concatenation of ProgramData and the GUID string.</p></figcaption></figure>

Outside of the said function, it then checks whether the provided value is a directory and that no error has occurred. If so, the function `sub_1400E36B0` is called, where the `lpFileName` value is set to the concatenation of the `ProgramData` directory and the machine `GUID`.

This means it checks whether the specified `C:\ProgramData\\{GUID}` directory exists.

<figure><img src="https://miro.medium.com/v2/resize:fit:716/1*PXLmPkL0mkdA3ZzczBU5xQ.png" alt="" width="563"><figcaption><p>Figure 9. Check whether the specified directory exists.</p></figcaption></figure>

The argument passed to `GetFileAttributesW` is a directory path concatenated by the previously analyzed function.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*wFzMJFuAZMqMZDHVRtoaJg.png" alt="" height="78" width="700"><figcaption><p>Figure 10. The specified directory to be checked is C:\ProgramData\{GUID}.</p></figcaption></figure>

However, since no directory such as `C:\ProgramData\\{GUID}` exists, an error is returned and the function `sub_1400E36B0` is skipped.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*ZH2EEqosgoGXy0WkrAA0NA.png" alt="" height="274" width="700"><figcaption><p>Figure 11. The specified directory does not exist.</p></figcaption></figure>

Inside the `sub_1400E36B0` function, the value of `a1` is copied into `v2`, where `a1` contains the `C:\ProgramData\\{GUID}` directory path. Later, `FileName` is assigned the value of `v2`, meaning that `FileName` now refer to the `C:\ProgramData\\{GUID}` directory.

After that, `v4` was assigned `\\*`, which appended to the end of the `FileName`. This change `FileName` into the `C:\ProgramData\\{GUID}\\*` directory format, meaning it will search for anything inside the `C:\ProgramData\\{GUID}` directory.

<figure><img src="https://miro.medium.com/v2/resize:fit:784/1*Hyn-vL7NqbQrhPfgMZZNTQ.png" alt="" width="563"><figcaption><p>Figure 12. Copying and concatenating to the FileName.</p></figcaption></figure>

Next, the function `FindFirstFileW` is called to check whether the directory path is not `.` or `..`, which refer to the current and parent directories.

This could mean that it tries to check whether the current directory contains any other files or subdirectories.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*CYNy72lEnXxIEcIWFl_sNA.png" alt="" height="122" width="700"><figcaption><p>Figure 13. Check that the directory is neither the current nor the parent directory.</p></figcaption></figure>

If the condition is met, the same logic is applied as in the previous analysis, but this time `PathName` is used as the copier, causing it to change to `C:\ProgramData\\{GUID}\` instead of just `C:\ProgramData\\{GUID}`, followed by the next file or directory name.

<figure><img src="https://miro.medium.com/v2/resize:fit:801/1*9NOEyYvWqGEFzUhY4-cQ4Q.png" alt="" width="563"><figcaption><p>Figure 14. Copying and concatenating to the PathName.</p></figcaption></figure>

Lastly, it checks whether each discovered item is a directory. If so, it recursively enumerates and deletes all contents of that directory. However, if no files or subdirectories remain, meaning the loop is exited, the function `RemoveDirectoryW` is then called to remove the parent directory itself.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*yXZfCgScGv5LAV2wJ7vOsQ.png" alt="" height="200" width="700"><figcaption><p>Figure 15. Enumeration and deletion of files and directories.</p></figcaption></figure>

The machine `GUID` directory is now created manually inside `ProgramData` for testing purposes.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*AWCDhTV2qgwsXNe-u836eg.png" alt="" width="563"><figcaption><p>Figure 16. Manually set up directories for testing purposes.</p></figcaption></figure>

When the condition is met, the value `C:\ProgramData\\{GUID}` is passed as an argument to the `sub_1400E36B0` function.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*gQ4pcnajmDe72wuBm0lopQ.png" alt="" height="81" width="700"><figcaption><p>Figure 17. If the directory exists, it is passed to the sub_1400E36B0 function.</p></figcaption></figure>

Step into the `sub_1400E36B0` function. Before the `DeleteFileW` function is called, the value `C:\ProgramData\\{GUID}\one.zip` is passed as its argument, as manually set up for testing purposes.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*VcP4QEDw3ieTBJB8a-M65g.png" alt="" height="152" width="700"><figcaption><p>Figure 18. The file one.zip is passed as an argument to be deleted.</p></figcaption></figure>

The `DeleteFileW` function is called successfully to delete the specified file. This logic applies similarly to other files or subdirectories within the current directory.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*lp3_BUsIPunXx21Key1a7A.png" alt="" width="563"><figcaption><p>Figure 19. The file one.zip is deleted successfully (1/2).</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*2juV17MbfeHFPvpTQSSzeQ.png" alt="" width="563"><figcaption><p>Figure 20. The file one.zip is deleted successfully (2/2).</p></figcaption></figure>

After everything has been deleted and nothing remains, `C:\ProgramData\\{GUID}` is finally passed as an argument to `RemoveDirectoryW` to delete the current directory.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*VwUYX1WEGGH6-0P7utZj1Q.png" alt="" height="107" width="700"><figcaption><p>Figure 21. The C:\ProgramData\{GUID} directory is passed to be deleted.</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*A8Y4_sE9WVZc2WFz81c1_g.png" alt="" width="563"><figcaption><p>Figure 22. The directory C:\ProgramData\{GUID} is deleted successfully.</p></figcaption></figure>

***

### Obfuscated Files or Information: Dynamic API Resolution (T1027.007) <a href="#dcc9" id="dcc9"></a>

It also implements a Dynamic API Resolution technique, particularly for network connections, by loading `wininet.dll`. Based on the loaded library and the functions used, this could mean that the stealer communicates with the threat actor over the HTTP protocol.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*ZGs97jg39Opp2BRo1DX3kg.png" alt="" width="563"><figcaption><p>Figure 23. Implementation of the Dynamic API Resolution technique.</p></figcaption></figure>

***

### Debugger Evasion (T1622) <a href="#c0b4" id="c0b4"></a>

In the same function, `sub_14000D610`, that implements the Dynamic API Resolution technique, another technique is applied. At `LABEL_13`, the function `IsDebuggerPresent` is called, and it returns a value of zero if a debugger is present.

<figure><img src="https://miro.medium.com/v2/resize:fit:334/1*6ntZz_oruv4lAfCHV4v3dQ.png" alt="" height="137" width="267"><figcaption><p>Figure 24. Implementation of the Debugger Evasion technique.</p></figcaption></figure>

If a zero value is returned from the function, indicating that it begins debug, the jump is taken and all remaining execution are skipped until the end of the program.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*lUq81fUtI2BMxOZZhr29CQ.png" alt="" width="563"><figcaption><p>Figure 25. If begin debug, skip all remaining important code until the end of the program (1/2).</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*OpLmjnGHsL9nNjH-KmtQRw.png" alt="" width="563"><figcaption><p>Figure 26. If begin debug, skip all remaining important code until the end of the program (2/2).</p></figcaption></figure>

***

### Data Staged: Local Data Staging (T1074.001) <a href="#id-482f" id="id-482f"></a>

If a debugger is not present, a call to the function `sub_1400DBBE0` is performed to enumerate system information, specifically the machine `GUID`. See [**Initial Indicator Removal: File Deletion (T1070.004)**](#id-3520) for more details.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*KD6qGL8lPm3lJjNciywoIA.png" alt="" height="244" width="700"><figcaption><p>Figure 27. Call to sub_1400DBBE0 to discover system information.</p></figcaption></figure>

However, these instructions can be executed due to the patching of the opcode to change the condition logic, allowing further analysis to be performed.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*rsqFrh7DAo2xmw3atouWqA.png" alt="" width="563"><figcaption><p>Figure 28. Editing opcodes for dynamic analysis.</p></figcaption></figure>

After the function `sub_1400DBBE0` is called, the value returned `C:\ProgramData\\{GUID}` is passed as an argument to `CreateDirectoryW` to create a directory at the specified target path.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*CWxe-CQA2PkVJ2OZZ7vKZw.png" alt="" height="128" width="700"><figcaption><p>Figure 29. The path C:\ProgramData\{GUID} is passed as an argument to be created.</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*co3XzYTPj47LxqQCW-h8BA.png" alt="" width="563"><figcaption><p>Figure 30. The directory C:\ProgramData\{GUID} is created successfully.</p></figcaption></figure>

***

### Impair Defenses: Disable or Modify Tools (T1562.001) <a href="#a17c" id="a17c"></a>

Under `LABEL_19`, a thread is created, and its entry point is where the process termination begins to execute. It starts with an infinite while loop, within which process enumeration and termination are performed. By calling the functions `CreateToolhelp32Snapshot`, `Process32FirstW`, `OpenProcess`, and `TerminateProcess`, the same logic is applied to other processes, as seen in Figure 33 and Figure 34.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*Wrw9etD0N7jrc3nLug6d_Q.png" alt="" height="465" width="700"><figcaption><p>Figure 31. Thread entry point containing a process termination.</p></figcaption></figure>

Where the delay is set to one second before the next process is enumerated and terminated.

<figure><img src="https://miro.medium.com/v2/resize:fit:521/1*gSc-RBlc4rUWYiX-JQdmcQ.png" alt="" width="563"><figcaption><p>Figure 32. The delay is set before the next process is enumerated and terminated.</p></figcaption></figure>

The list of processes to be terminated in the thread entry point is meant to perform anti-analysis, especially during dynamic analysis.

<figure><img src="https://miro.medium.com/v2/resize:fit:796/1*Rskme82weLgVQjefvXbeSA.png" alt="" width="563"><figcaption><p>Figure 33. The list of processes to be terminated (1/2).</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:695/1*2idU7ySe508nPEx--cbaXQ.png" alt="" width="563"><figcaption><p>Figure 34. The list of processes to be terminated (2/2).</p></figcaption></figure>

To perform further analysis of the stealer, the binary was patched to change the delay from one second to ten hours when attempting to enumerate and terminate processes.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*bPg1zvpMJRS4GbPWefMa2w.png" alt="" height="165" width="700"><figcaption><p>Figure 35. The binary is patched to change the delay from one second to ten hours.</p></figcaption></figure>

***

### Credentials from Password Stores: Credentials from Web Browsers (T1555.003) <a href="#b6fb" id="b6fb"></a>

In the function `sub_1400DC0C0`, it first tries to set a directory path for credential harvesting. To do this, the function `SHGetFolderPathW` is called with an interesting argument, `26`, which represent `CSIDL_APPDATA`, and the result is stored in `v246`.

<figure><img src="https://miro.medium.com/v2/resize:fit:583/1*upQg-oC-EXhbfKwweoPEHA.png" alt="" width="563"><figcaption><p>Figure 36. Retrieve the AppData path.</p></figcaption></figure>

The same applies to the second call to `SHGetFolderPathW`, but this time `28` is used, which represent `CSIDL_LOCAL_APPDATA`, and the result is stored in `v249`.

<figure><img src="https://miro.medium.com/v2/resize:fit:510/1*DtsvNzI3IwzV0fzlWDZF3g.png" alt="" width="563"><figcaption><p>Figure 37. Retrieve the Local AppData path.</p></figcaption></figure>

After these directory discovery technique are performed, string concatenation occurs using the string `Wallets` and the return value of the function `sub_1400DBBE0`, which is `C:\ProgramData\\{GUID}`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*NsEogZmk7vTlmPmiiWgDGA.png" alt="" height="186" width="700"><figcaption><p>Figure 38. A Wallets directory is created under C:\ProgramData\{GUID}.</p></figcaption></figure>

When all of the setup is complete, another round of string concatenation begins. This time, a browser related path is used with `v249`, which refer to `CSIDL_LOCAL_APPDATA` as seen in the previous analysis.

<figure><img src="https://miro.medium.com/v2/resize:fit:786/1*Ilv2A1PR22Di97JjWXx61w.png" alt="" width="563"><figcaption><p>Figure 39. A Chrome Extension path is used in concatenation.</p></figcaption></figure>

This logic is similar for any other path used for further credential harvesting. However, the values may vary, which’s depends on the browser related path used. It can either be `CSIDL_APPDATA` or `CSIDL_LOCAL_APPDATA`.

See the [**Conclusion**](#id-5ae9) for further details on the targeted browser extensions, including cryptocurrency wallets and password managers.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*q9ZFOjXK4QhpUxaE9VV51g.png" alt="" height="69" width="700"><figcaption><p>Figure 40. The Chrome extension settings path is concatenated.</p></figcaption></figure>

***

### Unsecured Credentials: Credentials In Files (T1552.001) <a href="#dfbd" id="dfbd"></a>

Another function shifts credential harvesting toward applications such as Telegram and Discord. Instead of `Wallets`, a directory named `Messengers` is created under the same parent directory.

<figure><img src="https://miro.medium.com/v2/resize:fit:839/1*Y6H7eFRfsbNeRuhY1pOPSA.png" alt="" width="563"><figcaption><p>Figure 41. A Messengers directory is used in concatenation.</p></figcaption></figure>

Similar to the previous credential harvesting process that retrieves credentials from web browsers, the same logic is used to discovered credentials such as tokens from applications.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*_z199Y1YK6IHKLZ3TWScbA.png" alt="" width="563"><figcaption><p>Figure 42. A Discord token is begin to looked for.</p></figcaption></figure>

Just as credential harvesting is performed on applications and browser extensions, the same is used for `FTP clients`.

<figure><img src="https://miro.medium.com/v2/resize:fit:846/1*gxVCPRJNcIW3uIFbEMRAzA.png" alt="" width="563"><figcaption><p>Figure 43. An FTP Clients directory is used in concatenation, and FileZilla is begin to looked for.</p></figcaption></figure>

After each credential harvesting function completes, the `CreateDirectoryW` function is called with the `lpPathName` argument set to a path `C:\ProgramData\\{GUID}\Wallets\`.

<figure><img src="https://miro.medium.com/v2/resize:fit:780/1*sJAbgFKvNWG2QUi1zB0iyQ.png" alt="" width="563"><figcaption><p>Figure 44. The directory is concatenated and created.</p></figcaption></figure>

At the first execution of the credential harvesting function, a set of directories is created under `C:\ProgramData\\{GUID}\Wallets\`, named after cryptocurrency related browser extensions and applications.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*OGUtva00eyKKr7nr30tpCw.png" alt="" width="563"><figcaption><p>Figure 45. List of targeted credentials from web browsers.</p></figcaption></figure>

However, when it comes to another credential harvesting function, a set of directories is created under `C:\ProgramData\\{GUID}\Messengers\`, named after messenger related applications.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*JJ_3OptmTcrMo1mTtNWR_w.png" alt="" width="563"><figcaption><p>Figure 46. List of targeted messenger applications.</p></figcaption></figure>

The same applies to credential harvesting for `FTP Clients`, which targets only FileZilla.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*RNf4PZxwAQjOD2oT_hABQw.png" alt="" width="563"><figcaption><p>Figure 47. List of targeted ftp client application.</p></figcaption></figure>

***

### Initial Screen Capture (T1113) <a href="#b204" id="b204"></a>

When all credential harvesting is complete, a screenshot is taken. For this purpose, libraries such as `gdiplus.dll` and `gdi32.dll` are loaded. So, various screenshot related functions can then be used, including `GdipCreateBitmapFromHBITMAP`, `GdipGetImageEncoders`, and `GdipSaveImageToFile`.

<figure><img src="https://miro.medium.com/v2/resize:fit:604/1*c4eGB97Xo65YHc6MMwYlCQ.png" alt="" width="563"><figcaption><p>Figure 48. A Windows internal API is called for screen capture.</p></figcaption></figure>

Now, the file is placed in the same directory where the harvested credentials is stored. The screenshot is named `Screenshot` with a `.jpg` extension, as it was hardcoded. Where the screenshot is named `Screenshot` with a `.jpg` extension, as it was hardcoded.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*a9h53GWKNtHdEYkPTdCySw.png" alt="" height="132" width="700"><figcaption><p>Figure 49. A screenshot is taken and saved in C:\ProgramData\{GUID}.</p></figcaption></figure>

***

### Software Discovery (T1518) <a href="#id-8465" id="id-8465"></a>

After the screenshot is taken, installed software is discovered under the `sub_1400DB6B0` function, where the collected information is saved to the file `Software_Info.txt`.

<figure><img src="https://miro.medium.com/v2/resize:fit:823/1*9o3jQn2yRCfOT-emGarFyw.png" alt="" width="563"><figcaption><p>Figure 50. A file named Software_Info.txt is used in concatenation.</p></figcaption></figure>

To do this, calls to the `MsiEnumProductExW` and `MsiGetProductInfoW` functions are performed with specific attributes defined, such as `ProductName`, `VersionString`, and `InstallDate`, this also includes the product ID of the installed software.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*1F5CTbHFveretQ3ZkuDYFA.png" alt="" height="263" width="700"><figcaption><p>Figure 51. A Windows Internal API is called for software discovery.</p></figcaption></figure>

The `Software_Info.txt` file is created in the same directory where the harvested credentials and screenshot image are stored.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*6Ue_Xva56bglnxsdns7NQw.png" alt="" height="114" width="700"><figcaption><p>Figure 52. A file named Software_Info.txt is written and saved in C:\ProgramData\{GUID}.</p></figcaption></figure>

***

### System Information Discovery (T1082) <a href="#id-0c17" id="id-0c17"></a>

The next thing to be discovered is system information. First, in the `sub_140011620` function, a file named `Info.txt` will be created.

<figure><img src="https://miro.medium.com/v2/resize:fit:679/1*vRmupff_oJe5LSADOMzKaQ.png" alt="" width="563"><figcaption><p>Figure 53. A file named “Info.txt” is created.</p></figcaption></figure>

After the file is created, various function calls are performed to gather information ranging from system details, such as CPU architecture and current virtual and physical memory usage, to the local time of the infected machine.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*pEjhIgjhHFOZT9EVmz4nkQ.png" alt="" width="563"><figcaption><p>Figure 54. A Windows Internal API is called for system information discovery.</p></figcaption></figure>

However, when checking the CPU architecture, only `x86` and `x64` architectures are supported, as these are the only ones written to the file, other architectures, such as `ARM`, are not included.

<figure><img src="https://miro.medium.com/v2/resize:fit:509/1*wlNU5LQsVUNnHOm3Vo8leg.png" alt="" width="563"><figcaption><p>Figure 55. Condition to check and provide the CPU architecture string to a text file.</p></figcaption></figure>

Lastly, after the discovery process is complete, the collected data is written to a file named `Info.txt` that was created earlier, which is placed in the same directory as the screenshot and harvested credentials.

<figure><img src="https://miro.medium.com/v2/resize:fit:841/1*o4gpkLSG4oAVtNDonGNEpA.png" alt="" width="563"><figcaption><p>Figure 56. A file named Info.txt is written and saved in C:\ProgramData\{GUID}.</p></figcaption></figure>

***

### Process Discovery (T1057) <a href="#id-20ba" id="id-20ba"></a>

In another function, `sub_140010F90`, a currently running windows process is discovered, and the collected data is written to a file named `Windows_Info.txt.`

<figure><img src="https://miro.medium.com/v2/resize:fit:805/1*8lG6lglWxylZFDzJHCdkjg.png" alt="" width="563"><figcaption><p>Figure 57. A file named Windows_Info.txt is used in concatenation.</p></figcaption></figure>

The target to be discovered is specified in a format to be written to the text file, which includes `WindowName`, `WindowTitle`, `WindowID`, and `ProcessName`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*PKNqByHeFg4ZV65tg-QVWQ.png" alt="" height="245" width="700"><figcaption><p>Figure 58. A provided format and target are used for discovery.</p></figcaption></figure>

By doing so, a specific function is called to perform the discovery technique and meet the provided text format, such as “K32EnumProcesses”, “OpenProcess”, “K32GetModuleFileNameExW”, “GetWindowThreadProcessId”, and “GetWindowTextW”.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*MRum9-ubs8NTXexSsIZAnw.png" alt="" width="563"><figcaption><p>Figure 59. A Windows Internal API is called for process discovery.</p></figcaption></figure>

In the end, a file was written with the collected data and placed in the same directory as screenshots, harvested credentials, and other discovered techniques.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*HEhA2WiQ3MffKzM9b6Plfg.png" alt="" height="119" width="700"><figcaption><p>Figure 60. A file named Windows_Info.txt is written and saved in C:\ProgramData\{GUID}.</p></figcaption></figure>

***

### Browser Information Discovery (T1217) <a href="#id-3752" id="id-3752"></a>

In the function `sub_1400DF950`, browser information begins to be discovered. First, a directory named `Browsers` is created under the path `C:\ProgramData\\{GUID}`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*vgbhOYzarVQBZ8R90JICKA.png" alt="" width="563"><figcaption><p>Figure 61. A browser directory begins to be created.</p></figcaption></figure>

After the directory is successfully created, the program sets the newly created directory as the current directory and then calls the important function `sub_140009620`.

<figure><img src="https://miro.medium.com/v2/resize:fit:458/1*N6F_0MepokVEjFgsvEjX7A.png" alt="" width="563"><figcaption><p>Figure 62. The current path is set to the most recently created directory.</p></figcaption></figure>

Before get inside the said function, at first, the function `sub_1400094C0` is returned with a path to `C:\Users\\<Username>\AppData\Local\Google\Chrome\User Data\Default\History`

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*pzhy9624HCf9QSLzPGpwLw.png" alt="" height="73" width="700"><figcaption><p>Figure 63. The return value of the Google Chrome history path concatenation.</p></figcaption></figure>

Then the said path is passed as an argument to the `sub_14009620` function for further information discovery

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*vLMPz3IzlLJ0kc2-xpEtgQ.png" alt="" height="74" width="700"><figcaption><p>Figure 64. The Google Chrome browser history is passed as an argument.</p></figcaption></figure>

However, when it comes to the second call of the `sub_1400094C0` function, the return value changes to the history path of the Vivaldi Browser.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*WJAqa6jP6svjRN4LLT_21Q.png" alt="" height="120" width="700"><figcaption><p>Figure 65. The second return value of the path concatenation is the Vivaldi browser.</p></figcaption></figure>

The logic remains the same, but what changes is the browser being targeted to retrieve its history, which is then passed to the `sub_14009620` function.

To get more information about the targeted browsers, see the [**Conclusion**](#id-5ae9).

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*YKbHi705lj7hxcvNcipeWQ.png" alt="" height="71" width="700"><figcaption><p>Figure 66. The third return value of the path concatenation is the Brave browser.</p></figcaption></figure>

Inside the function `sub_140009620`, an SQLite query is performed to retrieve fields from browser history, specifically targeting Google Chrome based browsers, in the format shown.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*YBRBAurDQq4TVjfTRohs7w.png" alt="" height="295" width="700"><figcaption><p>Figure 67. An SQLite query is performed to retrieve history data.</p></figcaption></figure>

By that, an implementation of SQLite is performed inside the `sub_14009A6A0` function, which is the function where the SQLite query is passed as an argument.

<figure><img src="https://miro.medium.com/v2/resize:fit:838/1*gEGW_Fk9EDEEjWdJrqKPtw.png" alt="" width="563"><figcaption><p>Figure 68. An API related to SQLite is used.</p></figcaption></figure>

After the SQLite query is completed, a file named `Chrome_History.txt` begins to concatenated. However, Google Chrome is the target browser passed as an argument to this function only when it is called for the first time. If the browser is Microsoft Edge, the file name will changes to `Edge_History.txt` instead.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*_X5pM7sIEPo08FEJedgHqg.png" alt="" width="563"><figcaption><p>Figure 69. A file named Chrome_History.txt begins to be concatenated.</p></figcaption></figure>

Lastly, the file `Chrome_History.txt` is passed as an argument and created using the `CreateFileW` function.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*KWKg300XesZnBtJtNTz1xg.png" alt="" width="563"><figcaption><p>Figure 70. A file named Chrome_History.txt is passed as an argument to be created.</p></figcaption></figure>

Since there is no history data in the Google Chrome browser, Figure 71 shows the Microsoft Edge browser instead, where the history data is passed to the “WriteFile” function to be written to a file.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*HFVdeNP33QU8y7H6iRidRw.png" alt="" height="88" width="700"><figcaption><p>Figure 71. Microsoft Edge history data is passed as an argument to be written.</p></figcaption></figure>

The results show the visited URL, the title of each URL, the number of times it was visited, and the most recent visit time. The list continues until the end of the browsers history.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*VVl7rgi2PPs9aYWZJqX7xA.png" alt="" height="260" width="700"><figcaption><p>Figure 72. The list of Microsoft Edge history data written to a text file.</p></figcaption></figure>

However, the file being created and written contains not only browsing history but also download history, both of which are written to the same directory.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*0l_oDr8nfGCmISGfNrL0og.png" alt="" height="149" width="700"><figcaption><p>Figure 73. The list of Microsoft Edge download history data written to a text file.</p></figcaption></figure>

***

### Archive Collected Data (T1560) <a href="#eb7e" id="eb7e"></a>

After the browser information is collected, the function `SHGetFolderPathW` is called to retrieve the common application data path, `C:\ProgramData`.

<figure><img src="https://miro.medium.com/v2/resize:fit:515/1*oabInrtzeRBJWOtb6qjndQ.png" alt="" width="563"><figcaption><p>Figure 74. Retrieved common application data path.</p></figcaption></figure>

The retrieved path is then passed to the `SetCurrentDirectoryW` function, whose purpose is to set the current path from `C:\ProgramData\\{GUID}\` to `C:\ProgramData`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*PiyF2WIfw3A4_fqUukxBzQ.png" alt="" width="563"><figcaption><p>Figure 75. The retrieved data path is used as the current path.</p></figcaption></figure>

After the current path has been set, a string concatenation is performed between the machine `GUID` and the `.zip` extension, resulting in `{GUID}.zip`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*u7nI87WbrarMWo3y1XyuqA.png" alt="" height="90" width="700"><figcaption><p>Figure 76. The GUID and archive extension are concatenated.</p></figcaption></figure>

Now, when the string is concatenated, it is passed to the function `sub_140002110`, which handles file creation. The file is created in the current path, `C:\ProgramData`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*KnEMd78fzKsbUR7TAv7_Rw.png" alt="" height="105" width="700"><figcaption><p>Figure 77. An archive file is created by calling the function sub_140002110.</p></figcaption></figure>

After the file is created, the function `sub_1400E7690` is called. This function performs file and directory discovery and stores the results in an archived format. Then, a string concatenation between `C:\ProgramData\\{GUID}\` and `\*.\*` is performed, resulting in `C:\ProgramData\\{GUID}\\*.*`.

This is used to discovered any files within the directory. If no files are found, directories are discovered next.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*k6UFlUVIB-_dRYE3FKtEgA.png" alt="" height="326" width="700"><figcaption><p>Figure 78. File and directory discovery is performed under the function sub_1400E7690.</p></figcaption></figure>

If there are no more files or directories to be discovered, the function returns. The process of writing to the archive is handled by the function `sub_140002DA0`, which is called after this function exits.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*IdnTj-Grj6AprFjGQ5CQ6w.png" alt="" height="167" width="700"><figcaption><p>Figure 79. If there is nothing left, the function exits.</p></figcaption></figure>

The created archive file does not contain any protected passwords. However, as shown in Figure 80, it contains only a “Browser” directory. This change was made intentionally to speed up dynamic analysis, and the other directories were manually deleted.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*Iqd5UkL4Ke4rxzpf5V-SKA.png" alt="" height="302" width="700"><figcaption><p>Figure 80. A magic header and archive records.</p></figcaption></figure>

***

### Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted Non-C2 Protocol (T1048.003) <a href="#f435" id="f435"></a>

After the data is harvested, including both credentials and system information, an exfiltration process is performed. First, the file size of the archived harvested data is retrieved.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*T3I3L7Z3SeZ9EXjzldcO2w.png" alt="" width="563"><figcaption><p>Figure 81. File size is being retrieved.</p></figcaption></figure>

Then, the `wsprintfA` function is used to write a formatted string into the `String` buffer. This includes an HTTP body data for the archive file transfer and the archive file itself, `v28`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*7ijXfG8fkKlsuSsakaw7cQ.png" alt="" width="563"><figcaption><p>Figure 82. HTTP body data is being written to the buffer.</p></figcaption></figure>

The value of `String` passed to the `lstrlenA` function for further buffer size calculation is the HTTP body data, which includes `form-data`, `form-name`, and `content-type`.

<figure><img src="https://miro.medium.com/v2/resize:fit:819/1*e9lJ8wXEDYDpE1TX0m0crg.png" alt="" width="563"><figcaption><p>Figure 83. The string passed as an argument to get the length is the HTTP body data.</p></figcaption></figure>

The length of `String` is used to calculate the number of bytes to read, which will be stored in a buffer to receive data when the `ReadFile` function is called. The file size, passed as an argument, is the size that was retrieved in the previous analysis.

<figure><img src="https://miro.medium.com/v2/resize:fit:838/1*7IyDN3fYTjCYHMLxeKzCeQ.png" alt="" width="563"><figcaption><p>Figure 84. An archived file is read, and its data is stored in v12.</p></figcaption></figure>

Now, the infinite while loop begins. In the second loop, the `InternetConnectA` function is called to open an HTTP session, with a five second delay set between each opening of the HTTP session attempts.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*aBMlsqfuxs_cQ0pmg-vCzg.png" alt="" width="563"><figcaption><p>Figure 85. An HTTP session is opened for exfiltration.</p></figcaption></figure>

Outside of that loop, a handle for the HTTP request is created by calling the `HttpOpenRequestA` function. The `v17`, passed as an argument, is the previously opened HTTP session from the earlier analysis, followed by the second argument, which is the IP address of the HTTP server.

Then, the `InternetOpenUrlA` function is called to open a connection, allowing the process to access the provided IP address. This loop also has a five second delay between each connection attempts.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*dYaT5opIr81fLYLtdwSqag.png" alt="" width="563"><figcaption><p>Figure 86. An HTTP session is established for exfiltration.</p></figcaption></figure>

After connection have been set up and is no failures occured. The function `HttpSendRequestA` is then called to send a request with `POST` method to the specified header, `/xopbixc/data.php`.

If the request is successfully sent, the `HttpQueryInfoA` function is called to receive the header information associated with the sent HTTP request.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*tZS6Vd23LR5D5jwxwzVpdQ.png" alt="" width="563"><figcaption><p>Figure 87. The HTTP request with the POST method is sent to the HTTP server.</p></figcaption></figure>

***

### Final Indicator Removal: File Deletion (T1070.004)

When the exfiltration process is complete, the `sub_1400E36B0` function is called to delete a directory named with the machines `GUID`. See [**Initial Indicator Removal: File Deletion (T1070.004)**](#id-3520) for more details.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*5iiwcSalv3hju-GRXTAC0A.png" alt="" height="117" width="700"><figcaption><p>Figure 88. A directory storing harvested data is passed to be deleted.</p></figcaption></figure>

Next, the archive file of harvested data that was recently exfiltrated is passed to the `DeleteFileW` function to be deleted.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*qYMZRPrqyWJByDqh7vQfXw.png" alt="" height="126" width="700"><figcaption><p>Figure 89. An archived file is passed to be deleted.</p></figcaption></figure>

***

### System Owner/User Discovery (T1033) <a href="#id-4e89" id="id-4e89"></a>

After the file was deleted, a function named `sub_14000D7A0` is called. Within this function, various system information are gathered. However, when the `GetUserNameA` and `GetComputerNameA` functions are called, if the information cannot be retrieved, the string `UNKNOWN` is used instead.

<figure><img src="https://miro.medium.com/v2/resize:fit:583/1*xqSvcMDJXMDMCZ7zNO31RA.png" alt="" width="563"><figcaption><p>Figure 90. System information discovered.</p></figcaption></figure>

Then, the path to Telegram is concatenated and used to check whether it exists at the specified location by calling a function such as `GetFileAttributesA`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*vPc249u0T39MJMfce7k18A.png" alt="" height="73" width="700"><figcaption><p>Figure 91. The path to Telegram is passed as an argument.</p></figcaption></figure>

Now, after all of the information discovery are completed, a string is then constructed using `swprintf` function. In this case, a specific format is defined as `uid=%s\&ver=%s\&username=%s\&cmpname=%s\&telegram=%d`.

<figure><img src="https://miro.medium.com/v2/resize:fit:650/1*pRc7hvjal8Y1avRPfdXxIQ.png" alt="" width="563"><figcaption><p>Figure 92. A string is being constructed using a specific format.</p></figcaption></figure>

The values used in this format represent to the information discovered earlier, ranging from the `UID` field to the `telegram` field. However, since the analysis lab does not have the Telegram application installed, the value of the `telegram` field is set to zero.

<figure><img src="https://miro.medium.com/v2/resize:fit:666/1*iYXshbaNVX2ZdSYHnSyTiQ.png" alt="" width="563"><figcaption><p>Figure 93. Discovered information used in the string construction process.</p></figcaption></figure>

If the string is successfully prepared and no error occurs during concatenation, an IP address is passed as an argument to the `sub_14000E190` function.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*VVSWUTEDIMdCpjHIteMWkQ.png" alt="" height="100" width="700"><figcaption><p>Figure 94. An IP address is passed to the sub_14000E190 function.</p></figcaption></figure>

Inside the `sub_14000E190` function, `HttpSendRequestA` is called. In this case, the `POST` method is used to send a request to the HTTP server.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*hymzulsrhCUYGu05Ug7G6g.png" alt="" width="563"><figcaption><p>Figure 95. A POST request is sent to an HTTP server.</p></figcaption></figure>

After the `POST` request is sent with the prepared data to the HTTP server, the `HttpQueryInfo` function is then called to receive the response from the request.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*2IxxW5m5slicweRB_fBVDQ.png" alt="" width="563"><figcaption><p>Figure 96. Response received from the HTTP server.</p></figcaption></figure>

If the HTTP server returns a status of `OK` or `200`, indicating that the request was successfully sent, the allocated memory is then cleaned up, as shown in Figures 97 and 98.

<figure><img src="https://miro.medium.com/v2/resize:fit:505/1*7wRycu0-U7StZlJKxbPA5w.png" alt="" width="563"><figcaption><p>Figure 97. Check for successfully sent request (1/2).</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:540/1*kChhcVgX5SUUasgmFzU4cA.png" alt="" height="459" width="432"><figcaption><p>Figure 98. Check for successfully sent request (2/2).</p></figcaption></figure>

***

### Final Screen Capture (T1113)

Now, the next function to be called is `sub_1400DFB60`. In this function, `CSIDL_APPDATA` path is retrieved, followed by calls to the `GetTickCount` and `srand` functions. After the path is retrieved and a random number is generated, a string is constructed in the `%80x.jpg` format.

<figure><img src="https://miro.medium.com/v2/resize:fit:696/1*rY4bW5g9LRSB6_zbyrHf9A.png" alt="" width="563"><figcaption><p>Figure 99. A random number is created.</p></figcaption></figure>

Next, various functions are called to perform a screen capture, see [**Initial Screen Capture (T1113)**](#b204) for more information.

<figure><img src="https://miro.medium.com/v2/resize:fit:666/1*Vxo7T3baV_LttTeGhIfbFg.png" alt="" width="563"><figcaption><p>Figure 100. Screen capture function called.</p></figcaption></figure>

As seen in Figure 101, a constructed string, representing a file named with a random number is passed to the `sub_14000E7B0` function.

<figure><img src="https://miro.medium.com/v2/resize:fit:830/1*wcLQ824pVHJaq_zuyu3gew.png" alt="" width="563"><figcaption><p>Figure 101. A recently created random number is used as a filename.</p></figcaption></figure>

Inside the `sub_1400E7B0` function, the current directory is set to `C:\Users\\<Username>\AppData\Roaming`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*sMNtg8N1vroRklhGPrK87A.png" alt="" height="100" width="700"><figcaption><p>Figure 102. The current directory is now set to \AppData\Roaming.</p></figcaption></figure>

Then, a file with a randomly generated name is passed as an argument to the `CreateFileW` function.

<figure><img src="https://miro.medium.com/v2/resize:fit:800/1*33y262JTNh3b7RfF2F10Xw.png" alt="" width="563"><figcaption><p>Figure 103. An image file was created.</p></figcaption></figure>

After the file is created, its size is retrieved. Then, an HTTP request body string is constructed using the `wsprintfA` function, followed by the creation of an HTTP request handle, with a delay of five seconds between attempts.

<figure><img src="https://miro.medium.com/v2/resize:fit:766/1*BNYT2PKi-rNgisdUVcUvCw.png" alt="" width="563"><figcaption><p>Figure 104. A POST body request is constructed.</p></figcaption></figure>

If the HTTP handle is successfully created, a `POST` request is then set up, using the constructed HTTP request body string to be sent to the HTTP server. After the request is sent to the HTTP server, the file that was sent is then deleted.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*UzBqAzMoOC7szPnkhzLHeA.png" alt="" width="563"><figcaption><p>Figure 105. A POST request with its body is sent to the HTTP server.</p></figcaption></figure>

As seen in Figure 106, the body of the `POST` request contains a `JPEG` magic header as well as a `Content-Disposition` field. The sub-field `name` is specified with the value `screen`.

<figure><img src="https://miro.medium.com/v2/resize:fit:875/1*P4JsFj5BlURMo-1HZT_KbQ.png" alt="" height="238" width="700"><figcaption><p>Figure 106. A POST request body contains an image magic header.</p></figcaption></figure>

***

### Execution Flow <a href="#e28a" id="e28a"></a>

<figure><img src="https://miro.medium.com/v2/resize:fit:658/1*K8Lg-Gnpg8dJWmPNlZmGVg.png" alt="" height="664" width="526"><figcaption><p>Figure 107. SVCStealer Execution Flow (1/2).</p></figcaption></figure>

<figure><img src="https://miro.medium.com/v2/resize:fit:325/1*Qq-jLlZQgr-ouLONZDWPRw.png" alt="" height="758" width="260"><figcaption><p>Figure 108. SVCStealer Execution Flow (2/2).</p></figcaption></figure>

***

### Conclusion <a href="#id-5ae9" id="id-5ae9"></a>

SVCStealer is written in C++. In the version selected for analysis, no packing method is used. However, several anti-analysis techniques are used, especially for dynamic analysis, such as terminating analysis tools including x64dbg, OllyDbg, and Procmon, and self-terminating when debugging is detected. The main targets include credentials (such as cryptocurrency wallets and password managers), messenger applications like Discord and Telegram, system information, system owner details, and screenshots. Data exfiltration to its C2 server is performed over an HTTP based protocol.

According to the research from Seqrite, the delivery method at the time the stealer was discovered involved a spear phishing technique. If this type of attack still occurs in an organization, it may be due to a lack of training among employees in other departments. Proper training and stricter rules may needed to prevent this type of situation.

The following is a list of messenger applications, cryptocurrency applications, and browser extensions, including cryptocurrency wallets and password managers, targeted by SVCStealer.

```
Browsers:

1. Google Chrome Browser
2. Microsoft Edge Browser
3. Brave Browser
4. Opera Browser
5. Yandex Browser
6. Vivaldi Browser
7. Comodo Browser
8. UR Browser

Cryptocurrency wallet browser extensions:

1. Metamask
2. Binance
3. TronLink
4. Phantom
5. TON Wallet
6. OKX Wallet
7. Trust Wallet
8. FRWT Secure DeFi Crypto Wallet
9. CoinWallet: BTC Crypto Wallet
10. Cirus
11. Internet Money
12. Ronin

Password manager browser extensions:

1. Keeper
2. LastPass
3. MultiPassword

Cryptocurrency wallet applications:

1. Exodus
2. Electrum
3. Bitcoin
4. Atomic

Messenger applications:

1. Messengers
2. Telegram
3. 64gram
4. Discord
5. Tox

FTP client:

1. FileZilla
```

***

### IOCs <a href="#id-36f6" id="id-36f6"></a>

```
SHA256: 7170e9b5258fe6f34506ee044f0ead290b9349b756e5a75cb6aea9526139ae4d
MD5: bcd48c601c8624b503b7cac700a15600
C2: 62[.]60[.]226[.]159
```

***

### YARA Rule <a href="#ac92" id="ac92"></a>

```
rule Mal_WIN_SVC_Stealer_PE {
        meta:
                description = "Use to detect SVCStealer."
                author = "Phatcharadol Thangplub"
                date = "01-28-2026"
                reference = "https://www.seqrite.com/blog/svc-new-stealer-on-the-horizon/"

        strings:
                $s1 = "[Machine]" fullword wide
                $s2 = "[Processes]" fullword wide
                $s3 = "Antivirus:" fullword wide
                $s4 = "qspbhauhcrhn" fullword ascii
                $s5 = "uid=%s&ver=%s&username=%s&cmpname=%s&telegram=%d" fullword ascii
                $s6 = "Content-Disposition: form-data; name=\"log\"; filename=\"%s\"" fullword ascii
                
                /*
                        Concatenating directory path for deletion.
                */
                $hex1 = { 4? 2b d3 0f 1f 00 0f b7 01 66 89 04 0a 4? 8d 49 02 66 85 c0 
                        75 ?? 4? 8d ?? ?4 70 02 00 00 4? 83 e9 02 0f 1f 40 00 66 83 7? 
                        ?? 00 4? 8d ?? 02 75 ?? 8b 05 [4] 89 0? 4? 8d ?? ?4 70 02 00 
                        00 4? 83 e8 02 90 66 83 7? ?? 00 4? 8d ?? 02 75 ?? 4? 8d ?? 
                        ?4 4c 33 d2 0f 1f 40 00 66 66 0f 1f 84 00 00 00 00 00 4? 0f 
                        b7 0c ?? 66 89 0c ?? 4? 8d 52 01 66 85 c9 75 }

        condition:
                uint16(0) == 0x5A4D and filesize >= 80KB and filesize <= 2MB and ((3 of ($s*)) or $hex1)
}
```

***

### Sigma Rule <a href="#f3ca" id="f3ca"></a>

```yml
title: SVCStealer - File or Directory Interaction on an Infected Machine.
name: file_or_directory_interaction_on_an_infected_machine
id: af0cc1b6-7176-42e5-a398-22350312a2a7
status: experimental
description: Use to hunt SVCStealer file or direcory interaction.
references:
        - https://attack.mitre.org/
        - https://any.run/malware-trends/svcstealer/
        - https://www.seqrite.com/blog/svc-new-stealer-on-the-horizon/
author: Phatcharadol Thangplub
date: 2026-01-28
modified: 2026-03-07
tags:
        - attack.T1083
        - attack.T1560
        - attack.T1070.004
        - attack.T1074.001
logsource:
        product: windows
        service: sysmon
detection:
        selection_event_id:
                - EventCode: 11
                - EventCode: 23
        selection_wild_targeted_file_or_directory:
                TargetFilename|endswith:
                        - "C:\\ProgramData\\*.zip"
                        - "C:\\ProgramData\\*\\*.jpg"
                        - "C:\\ProgramData\\*\\*.txt"
                TargetFilename|contains:
                        - "C:\\ProgramData\\*\\Wallets"
                        - "C:\\ProgramData\\*\\Browsers"
                        - "C:\\ProgramData\\*\\Messengers"
                        - "C:\\ProgramData\\*\\FTP Clients"
                        - "C:\\ProgramData\\*\\FileGrabber"
        condition: selection_event_id and selection_wild_targeted_file_or_directory
falsepositives:
        - Unknown
level: high
---
title: SVCStealer - Connection to Web-Based C2
name: connection_to_web_based_c2
id: 13099a64-622d-47e8-b395-9116625d14ec
status: experimental
description: Use to hunt SVCStealer web-based C2 connections.
references:
        - https://attack.mitre.org/
        - https://any.run/malware-trends/svcstealer/
        - https://www.seqrite.com/blog/svc-new-stealer-on-the-horizon/
author: Phatcharadol Thangplub
date: 2026-01-28
modified: 2026-03-07
tags:
        - attack.T1048.003
logsource:
        product: windows
        service: sysmon
detection:
        selection_network_connection:
                EventCode: 3
                Protocol: tcp
                DestinationIp:
                        - "62.60.226.159"
                        - "176.113.115.149"
                        - "185.39.17.158"
                        - "185.81.68.156"
                        - "194.38.21.76"
                        - "77.90.153.62"
                        - "185.39.17.233"
        selection_dns_query:
                EventCode: 22
                QueryName|startswith:
                        - "diamotrix"
        condition: selection_network_connection or selection_dns_query
falsepositives:
        - Unknown
level: high
---
title: SVCStealer - Correlate File or Directory Interaction and C2 Connection
id: 05ab89db-9e60-4f41-b475-75145494f255
correlation:
        type: temporal
        rules:
                - file_or_directory_interaction_on_an_infected_machine
                - connection_to_web_based_c2
        group-by:
                - Computer
                - User
                - ProcessId
                - Image
        timespan: 2m
```

***

### Additional Resources <a href="#id-8d83" id="id-8d83"></a>

<https://attack.mitre.org/>

<https://any.run/malware-trends/svcstealer/>

<https://www.seqrite.com/blog/svc-new-stealer-on-the-horizon/>

<https://www.cyfirma.com/news/weekly-intelligence-report-28-mar-2025/>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://mapol.gitbook.io/home/blog/malware-analysis/stealer/svcstealer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
