Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Hiding users (net.exe and lusrmgr.msc) #74

Open
MaggieKong opened this issue Mar 26, 2024 · 20 comments
Open

Hiding users (net.exe and lusrmgr.msc) #74

MaggieKong opened this issue Mar 26, 2024 · 20 comments

Comments

@MaggieKong
Copy link

would you add local user hidden from net.exe,net1.exe and lusrmgr.msc in the future?

@bytecode77
Copy link
Owner

A user has lots of traces all over the system, such as its files, an entire registry hive, etc. etc... What's your intention? Why do you consider net.exe to be enough to hide a user's activity? Maybe I can help you better when I understand your intensions a bit better.

@MaggieKong
Copy link
Author

windows has RDP service and control over RDP service required Admin User.the most obvious way to list all local users is net.exe,net1.exe and lusrmgr.msc.
hooking NetUserEnum can hide users from "net.exe user" and "net1.exe user" command,but it can't hide users from "net.exe localgroup administrators" command
hooking netapi32 api seems like no effect on lusrmgr.msc

@bytecode77
Copy link
Owner

Thanks for doing some research upfront. I've checked what this function is doing. It eventually calls NdrClientCall3, which is a RPC.

Call stack: netapi32.dll!NetUserEnum calls samcli.dll!NetUserEnum, which calls samlib.dll!SamEnumerateUsersInDomain

This is the call to NdrClientCall3.

    if ( v15 )
    {
      if ( v15 != 1 )
        return 3221225659i64;
      LODWORD(v27) = v11;
      LODWORD(v25) = v12;
      LODWORD(v24) = v31;
      v16.Pointer = NdrClientCall3(
                      (MIDL_STUBLESS_PROXY_INFO *)&pProxyInfo,
                      0x48u,
                      0i64,
                      v28.Simple,
                      a3,
                      v24,
                      v25,
                      &hMem,
                      v27,
                      v14).Pointer;
      v17 = (unsigned int)v16.Pointer;
      v28.Pointer = v16.Pointer;
    }
    else
    {
      LODWORD(v26) = v11;
      LODWORD(v24) = v31;
      v29.Pointer = NdrClientCall3(
                      (MIDL_STUBLESS_PROXY_INFO *)&pProxyInfo,
                      0xDu,
                      0i64,
                      v28.Simple,
                      a3,
                      v24,
                      &hMem,
                      v26,
                      v14).Pointer;
      v17 = (unsigned int)v29.Pointer;
    }

I've done only some quick research, but didn't check where this RPC is going. It would be best to hook the function at the remote endpoint (on the local computer of course). If this is not possible, hooking NdrClientCall3 may do it. I've googled and this function seems to be a popular target to hook.

I think this function is filling an array with the users. Would you like to hook it and inspect the output?

@bytecode77 bytecode77 changed the title todo Hiding users (net.exe and lusrmgr.msc) Mar 28, 2024
@MaggieKong
Copy link
Author

MaggieKong commented Mar 29, 2024

hooking NetUserEnum would do the trick about(net.exe user or net1.exe user),but not for "net.exe localgroup administrators" or "net1.exe localgroup administrators" command.trying NetGroupGetUsers,NetLocalGroupGetMembers and NetQueryDisplayInformation,but no luck.

@bytecode77
Copy link
Owner

Have you tried hooking NdrClientCall3? I didn't try, but I think it's always called, regardless of which app. You always want to hook the lowest level, not the higher level WinAPI functions.

@MaggieKong
Copy link
Author

MaggieKong commented Mar 29, 2024

I will try

@MaggieKong
Copy link
Author

there is an issue by hook NdrClientCall3
CLIENT_CALL_RETURN RPC_VAR_ENTRY NdrClientCall3(
MIDL_STUBLESS_PROXY_INFO *pProxyInfo,
unsigned long nProcNum,
void *pReturnValue,
...
);

static CLIENT_CALL_RETURN RPC_VAR_ENTRY HookedNdrClientCall3(MIDL_STUBLESS_PROXY_INFO* pProxyInfo, unsigned long nProcNum, void* pReturnValue, ...)
{
va_list args;
va_start(args, pReturnValue);
CLIENT_CALL_RETURN dwResult = OriginalNdrClientCall3(pProxyInfo, nProcNum, pReturnValue,args);
va_end(args);

return dwResult;

}

try hooking like this,NdrClientCall3 get trigged but result in The binding handle is invalid when use net.exe user command.no sure how to call the original api based on that api defination.

@bytecode77
Copy link
Owner

I've disassembled rpcrt4.dll and found the function definition:

CLIENT_CALL_RETURN NdrClientCall3(MIDL_STUBLESS_PROXY_INFO *pProxyInfo, unsigned int nProcNum, void *pReturnValue, ...)

So first, nProcNumis an int, which is 4 bytes in a 32-bit process and 8 bytes in a 64-bit process. You have a long there, which is always 4 bytes. This might break the following parameters in x64.

I also wondered that such a low level function acutally uses argument lists, but it does. However, it calls NdrpClientCall3 after doing some parameter checking and converting the argument list to an array. It's worth hooking and looking at calls to this function, I guess.

Just to let you know, it's perfectly normal to spend weeks on figuring out one silly function. I've spent ages on figuring out the NT_NSI_PARAM struct. There is no documentation on that struct other than what I have figured out myself. That's why every single feature of a rootkit takes ages to implement, because 95% of the time I've spent in IDA.

@MaggieKong
Copy link
Author

MaggieKong commented Mar 30, 2024

the NdrClientCall3 definetion is from rpcndr.h
NdrpClientCall3 is not exported in any dll.
still lwarning how to use IDA .

@bytecode77
Copy link
Owner

IDA is a nice thing to learn, if you regularly work with hooks, exploits, etc...

You can hook a function that isn't exported, as long as you know the function pointer. You can get it using GetFunction, which I use to retrieve functions that are not exported, such as in R77_NtCreateThreadEx.

Dunno, if NdrpClientCall3 is the relevant function to hook, though.

@MaggieKong
Copy link
Author

found an issue today.After install the rootkit, "net.exe localgroup" will always return the error "System error 234 has occurred.More data is available."
It occurs in all Windows Server,but Windows 10 works fine
BTW,r77 probably not compatable with windows server 2008,once the rootkit installed,the system acting weird.

@vps
Copy link

vps commented Oct 31, 2024

found an issue today.After install the rootkit, "net.exe localgroup" will always return the error "System error 234 has occurred.More data is available." It occurs in all Windows Server,but Windows 10 works fine BTW,r77 probably not compatable with windows server 2008,once the rootkit installed,the system acting weird.

The below should resolve the errors being described.

1. For Error 234 (ERROR_MORE_DATA):

// Current problematic pattern
NetLocalGroupEnum(server, level, &buffer, prefmaxlen, &entriesread, &totalentries, &resumehandle)

// Solution: Implement proper buffer handling
DWORD FixNetLocalGroupEnum(LPCWSTR servername) {
    LPBYTE buffer = NULL;
    DWORD entriesread = 0;
    DWORD totalentries = 0;
    DWORD_PTR resumehandle = 0;
    
    do {
        DWORD result = NetLocalGroupEnum(
            servername,
            0,  // Use level 0 first for names only
            &buffer,
            MAX_PREFERRED_LENGTH,  // Let system allocate needed size
            &entriesread,
            &totalentries,
            &resumehandle
        );
        
        if (result != NERR_Success && result != ERROR_MORE_DATA)
            return result;
            
        // Process buffer here
        NetApiBufferFree(buffer);
    } while (resumehandle != 0);
}

2. For NdrClientCall3 hooking:

typedef struct _NDR_PROC_CONTEXT {
    MIDL_STUBLESS_PROXY_INFO* pProxyInfo;
    UINT32 ProcNum;
    void* pReturnValue;
    SIZE_T StackSize;
    PVOID Args[];
} NDR_PROC_CONTEXT, *PNDR_PROC_CONTEXT;

// Correct x64 hooking
CLIENT_CALL_RETURN NTAPI HookedNdrClientCall3(
    MIDL_STUBLESS_PROXY_INFO* pProxyInfo,
    unsigned int procNum,     // Changed from long to match platform size
    void* pReturnValue,
    ...
) {
    NDR_PROC_CONTEXT ctx;
    va_list args;
    va_start(args, pReturnValue);
    
    // Preserve stack alignment for x64
    ctx.pProxyInfo = pProxyInfo;
    ctx.ProcNum = procNum;
    ctx.pReturnValue = pReturnValue;
    
    // Call original with preserved context
    CLIENT_CALL_RETURN result = ((PFN_NDRCLIENTCALL3)OriginalNdrClientCall3)(
        ctx.pProxyInfo,
        ctx.ProcNum,
        ctx.pReturnValue,
        va_arg(args, void*)  // Properly advance va_list
    );
    
    va_end(args);
    return result;
}

Key changes:

  1. Use MAX_PREFERRED_LENGTH for dynamic buffer allocation
  2. Implement resumehandle loop for complete enumeration
  3. Proper x64 alignment in NdrClientCall3 hook
  4. Preserve RPC binding context

Next steps would be to:

  1. Test buffer handling on Server 2012+ first
  2. Verify x64/x86 compatibility
  3. Test RPC binding persistence

@bytecode77
Copy link
Owner

I created a new branch NdrClientCall3 to test hooking of the NdrClientCall3 function. WARNING: Do not inject all processes! Only inject one process at a time.

To test it, I ran lusrmgr.msc and injected the mmc.exe process, which displays an empty list or crashes. @vps You seem to have gotten familiar with the function and I assume you did some testing yourself and that your tests didn't crash. Would you share your results with me? Do you see anything wrong with the code I pushed onto that branch?

@MaggieKong
Copy link
Author

MaggieKong commented Nov 2, 2024 via email

@MaggieKong
Copy link
Author

runing lusrmgr.msc On windows server 2012,
image

@MaggieKong
Copy link
Author

running taskmgr.exe
image

@MaggieKong
Copy link
Author

I didn't install R77,I will code a dll for NdrClientCall3 hook,and set the AppInit DLLs to load that dll would load from certain exe like mmc.exe,taskmgr.exe,quser.exe and ets,most of them crashed

@MaggieKong
Copy link
Author

image

@bytecode77
Copy link
Owner

I know that it's crashing, just wondering if @vps has anything to share before I go down the rabbit hole myself. I thought that he might made it work since he shared the hook. Thanks for sharing the results!

@MaggieKong
Copy link
Author

I did try different approach to make that hook work,but no luck

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

No branches or pull requests

3 participants