Create dataset
ctu19 %>% filter(State!="") %>% nrow()
[1] 27545
names(ctu19)
[1] "State" "class" "modelsize"
skim(ctu19 %>% mutate(class=as.factor(class)))
── Data Summary ────────────────────────
Values
Name ctu19 %>% mutate(class = ...
Number of rows 27545
Number of columns 3
_______________________
Column type frequency:
character 1
factor 1
numeric 1
________________________
Group variables None
── Variable type: character ──────────────────────────────────────────────────────────────────────────────────────────
skim_variable n_missing complete_rate min max empty n_unique whitespace
1 State 0 1 1 99997 0 16663 0
── Variable type: factor ─────────────────────────────────────────────────────────────────────────────────────────────
skim_variable n_missing complete_rate ordered n_unique top_counts
1 class 0 1 FALSE 2 Bot: 25945, Nor: 1600
── Variable type: numeric ────────────────────────────────────────────────────────────────────────────────────────────
skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
1 modelsize 0 1 663. 6156. 1 12 56 221 99997 ▇▁▁▁▁
create_histogram<-function(x){
valid_characters <- "$abcdefghiABCDEFGHIrstuvwxyzRSTUVWXYZ0123456789" %>% str_split("")
valid_characters <- valid_characters[[1]]
valid_characters[48]="\\."
valid_characters[49]="\\,"
valid_characters[50]="\\+"
valid_characters[51]="\\*"
freq<- (x %>% map(function(x) str_count(x,valid_characters)) %>% unlist() %>% matrix( ncol = 51, byrow = TRUE) %>% colSums())
freq<-freq/ sum( str_count(x,".") )
plot<-data.frame(freq=freq,symbols=valid_characters) %>%
ggplot()+
geom_col(aes(x=symbols,y=freq),fill='black',col='black')+
theme_bw()
plot
}
n <- (ctu19 %>% filter(class == "Normal" & modelsize <100))$State
nh<-create_histogram(n)
nh <- nh + labs(title="CTU19 seq char distribution for Normal [modelsize <100]")
m <- (ctu19 %>% filter(class != "Normal" & modelsize <100))$State
mh<-create_histogram(m)
mh <- mh + labs(title="CTU19 seq char distribution for Malware [modelsize <100]")
gridExtra::grid.arrange(nh,mh)

#source("preprocess.R")
#datasets<-build_train_test(datasetfile = "datasets/ctu13subs.csv",maxlen = ctu_maxlen)
# WARNING: to avoid regenerating de train and test sets, just uncomments the following lines
# WARNING: there is no guarantee the files saved correspond to argencon.csv. If unsure, just re-run build_train_test()
load(file='datasets/.train_dataset_keras.rd')
load(file='datasets/.test_dataset_keras.rd')
datasets<-list()
datasets$train<-train_dataset_keras
datasets$test<-test_dataset_keras
### Function Definitions ####
get_predictions <- function(model, test_dataset_x,threshold=0.5) {
predsprobs<-model %>% predict(test_dataset_x, batch_size=256)
preds<-ifelse(predsprobs>threshold,1,0)
return (preds)
}
summary(model)
_______________________________________________________________________________________________________________________________________________________
Layer (type) Output Shape Param #
=======================================================================================================================================================
input_1 (InputLayer) (None, 400) 0
_______________________________________________________________________________________________________________________________________________________
embedding (Embedding) (None, 400, 128) 6528
_______________________________________________________________________________________________________________________________________________________
lstm (LSTM) (None, 128) 131584
_______________________________________________________________________________________________________________________________________________________
dropout (Dropout) (None, 128) 0
_______________________________________________________________________________________________________________________________________________________
dense (Dense) (None, 1) 129
=======================================================================================================================================================
Total params: 138,241
Trainable params: 138,241
Non-trainable params: 0
_______________________________________________________________________________________________________________________________________________________
test_results<-data.frame(predicted_class=preds,class=ifelse(grepl("Normal",datasets$test$label) ,0,1) ,domain=datasets$test$domain,label=datasets$test$label)
#test_results
caret::confusionMatrix(as.factor(test_results$predicted_class),as.factor(test_results$class), positive='1', mode="everything" )
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 385 74
1 95 7710
Accuracy : 0.9795
95% CI : (0.9763, 0.9825)
No Information Rate : 0.9419
P-Value [Acc > NIR] : <2e-16
Kappa : 0.8092
Mcnemar's Test P-Value : 0.1239
Sensitivity : 0.9905
Specificity : 0.8021
Pos Pred Value : 0.9878
Neg Pred Value : 0.8388
Precision : 0.9878
Recall : 0.9905
F1 : 0.9892
Prevalence : 0.9419
Detection Rate : 0.9330
Detection Prevalence : 0.9445
Balanced Accuracy : 0.8963
'Positive' Class : 1
fp<-(test_results %>% mutate(modelsize=str_count(domain,".")) %>% filter(class == 0 & predicted_class == 1))
fn<-(test_results %>% mutate(modelsize=str_count(domain,".")) %>% filter(class == 1 & predicted_class == 0))
tp<-(test_results %>% mutate(modelsize=str_count(domain,".")) %>% filter(class == 1 & predicted_class == 1))
tn<-(test_results %>% mutate(modelsize=str_count(domain,".")) %>% filter(class == 0 & predicted_class == 0))
fp_domain<-fp$domain
tp_domain<-tp$domain
fn_domain<-fn$domain
tn_domain<-tn$domain
fp_h<-create_histogram(fp_domain)
fp_h <- fp_h + labs(title="CTU19 seq char distribution for False Positive")
#fp_h <- fp_h + ylim(0,500)
tp_h<-create_histogram(tp_domain)
tp_h <- tp_h + labs(title="CTU19 seq char distribution for True Positive")
#tp_h <- tp_h + ylim(0,500)
fn_h<-create_histogram(fn_domain)
fn_h <- fn_h + labs(title="CTU19 seq char distribution for False Negative")
tn_h<-create_histogram(tn_domain)
tn_h <- tn_h + labs(title="CTU19 seq char distribution for True Negative")
gridExtra::grid.arrange(fp_h,tp_h,fn_h,tn_h,ncol=1)

#library(scales)
#tp_h + scale_y_continuous(limits=c(0,1000),oob = rescale_none)
#fp_h + scale_y_continuous(limits=c(0,1000),oob = rescale_none)

pca 2D proyection
plotly::plot_ly(pca_data , type="scatter3d",
x = ~PC1, y = ~PC2, z = ~PC3, color = ~res, symbol = ~label,
colors = c('blue', 'orange',"red","green"),
opacity=0.5, marker = list(size = 3),text = ~domain)
No scatter3d mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
LS0tCnRpdGxlOiAiQ1RVMTkiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShza2ltcikKYGBgCgpgYGB7cn0KY3R1MTk8LXJlYWRfY3N2KCJkYXRhc2V0cy9jdHUxOV9yZXN1bHQuY3N2IikKY3R1MTkgJT4lIGdyb3VwX2J5KExhYmVsTmFtZSkgJT4lIHN1bW1hcmlzZShuPW4oKSkKYGBgCiMgQ3JlYXRlIGRhdGFzZXQKYGBge3J9CmN0dTE5PC0gY3R1MTkgJT4lIHNlbGVjdChTdGF0ZSxMYWJlbE5hbWUpIApuYW1lcyhjdHUxOSk8LWMoIlN0YXRlIiwiY2xhc3MiKQpjdHUxOSRTdGF0ZSA8LSBjdHUxOSRTdGF0ZSAlPiUgc3Vic3RyKDQsMTAwMDAwKQpjdHUxOTwtY3R1MTkgJT4lIGZpbHRlcihTdGF0ZSE9IiIpCgpjdHUxOSAlPiUgbnJvdygpCmN0dTE5ICU+JSBncm91cF9ieShjbGFzcykgJT4lIHN1bW1hcml6ZShuPW4oKSkKY3R1MTkgJT4lIHdyaXRlX2NzdigiZGF0YXNldHMvY3R1MTlzdWJzLmNzdiIpCm5hbWVzKGN0dTE5KQpgYGAKCmBgYHtyfQpjdHUxOTwtcmVhZHI6OnJlYWRfY3N2KCJkYXRhc2V0cy9jdHUxOXN1YnMuY3N2IikKCmN0dTE5PC1jdHUxOSAlPiUgbXV0YXRlKG1vZGVsc2l6ZT1zdHJfY291bnQoU3RhdGUsIi4iKSkgCmN0dTE5X2NsZWFuZWQ8LWN0dTE5ICU+JSBmaWx0ZXIgKCFpcy5uYShQb3J0KSkKCmN0dTE5X2NsZWFuZWQgJT4lIGZpbHRlcihQb3J0IDwgMTAyNCkgJT4lIGdyb3VwX2J5KG1vZGVsc2l6ZSxQb3J0KSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUodG90YWw9c3VtKG4pKSAKCmN0dTE5X2NsZWFuZWQgJT4lIGZpbHRlcihtb2RlbHNpemU8NCkgJT4lIHNlbGVjdChTdGF0ZSkKCmN0dTE5X2NsZWFuZWQkU3RhdGUgPC0gY3R1MTlfY2xlYW5lZCRTdGF0ZSAlPiUgc3Vic3RyKDQsNTAwMDAwMCkKZ2dwbG90KGN0dTE5X2NsZWFuZWQgJT4lIGZpbHRlcihQb3J0IDwgMTAyNCkpKwogIGdlb21fYm94cGxvdChhZXMoeD1hcy5mYWN0b3IoWDEpLHk9bW9kZWxzaXplKSkrCiAgdGhlbWVfYncoKQogIApuYW1lcyhjdHUxOSkKYGBgCmBgYHtyfQpjdHUxOTwtcmVhZHI6OnJlYWRfY3N2KCJkYXRhc2V0cy9jdHUxOXN1YnMuY3N2IikKY3R1MTk8LWN0dTE5ICU+JSBtdXRhdGUobW9kZWxzaXplPXN0cl9jb3VudChTdGF0ZSwiLiIpKSAKY3R1MTkgJT4lIGZpbHRlcihtb2RlbHNpemUgPjEwMCkgJT4lIGdyb3VwX2J5KGNsYXNzKSAlPiUgc3VtbWFyaXNlKG49bigpKQoKY3R1MTkgJT4lIG5yb3coKQpzdW1tYXJ5KGN0dTE5KQpza2ltKGN0dTE5ICU+JSBtdXRhdGUoY2xhc3M9YXMuZmFjdG9yKGNsYXNzKSkpCmBgYAoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTB9CmNyZWF0ZV9oaXN0b2dyYW08LWZ1bmN0aW9uKHgpewogIHZhbGlkX2NoYXJhY3RlcnMgPC0gIiRhYmNkZWZnaGlBQkNERUZHSElyc3R1dnd4eXpSU1RVVldYWVowMTIzNDU2Nzg5IiAlPiUgc3RyX3NwbGl0KCIiKQogIHZhbGlkX2NoYXJhY3RlcnMgPC0gdmFsaWRfY2hhcmFjdGVyc1tbMV1dIAogIHZhbGlkX2NoYXJhY3RlcnNbNDhdPSJcXC4iCiAgdmFsaWRfY2hhcmFjdGVyc1s0OV09IlxcLCIKICB2YWxpZF9jaGFyYWN0ZXJzWzUwXT0iXFwrIgogIHZhbGlkX2NoYXJhY3RlcnNbNTFdPSJcXCoiCgogIGZyZXE8LSAoeCAlPiUgbWFwKGZ1bmN0aW9uKHgpIHN0cl9jb3VudCh4LHZhbGlkX2NoYXJhY3RlcnMpKSAlPiUgdW5saXN0KCkgJT4lIG1hdHJpeCggbmNvbCA9IDUxLCBieXJvdyA9IFRSVUUpICU+JSBjb2xTdW1zKCkpCiAgZnJlcTwtZnJlcS8gc3VtKCBzdHJfY291bnQoeCwiLiIpICkKICBwbG90PC1kYXRhLmZyYW1lKGZyZXE9ZnJlcSxzeW1ib2xzPXZhbGlkX2NoYXJhY3RlcnMpICU+JQogIGdncGxvdCgpKwogIGdlb21fY29sKGFlcyh4PXN5bWJvbHMseT1mcmVxKSxmaWxsPSdibGFjaycsY29sPSdibGFjaycpKwogIHRoZW1lX2J3KCkKICBwbG90Cn0KbiA8LSAoY3R1MTkgJT4lIGZpbHRlcihjbGFzcyA9PSAiTm9ybWFsIiAmIG1vZGVsc2l6ZSA8MTAwKSkkU3RhdGUgCgpuaDwtY3JlYXRlX2hpc3RvZ3JhbShuKQpuaCA8LSBuaCArICBsYWJzKHRpdGxlPSJDVFUxOSBzZXEgY2hhciBkaXN0cmlidXRpb24gZm9yIE5vcm1hbCBbbW9kZWxzaXplIDwxMDBdIikKCm0gPC0gKGN0dTE5ICU+JSBmaWx0ZXIoY2xhc3MgIT0gIk5vcm1hbCIgJiBtb2RlbHNpemUgPDEwMCkpJFN0YXRlIAoKbWg8LWNyZWF0ZV9oaXN0b2dyYW0obSkKbWggPC0gbWggKyAgbGFicyh0aXRsZT0iQ1RVMTkgc2VxIGNoYXIgZGlzdHJpYnV0aW9uIGZvciBNYWx3YXJlIFttb2RlbHNpemUgPDEwMF0iKQoKZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UobmgsbWgpCgpgYGAKYGBge3J9CiNzb3VyY2UoInByZXByb2Nlc3MuUiIpCiNkYXRhc2V0czwtYnVpbGRfdHJhaW5fdGVzdChkYXRhc2V0ZmlsZSA9ICJkYXRhc2V0cy9jdHUxM3N1YnMuY3N2IixtYXhsZW4gPSBjdHVfbWF4bGVuKQojIFdBUk5JTkc6IHRvIGF2b2lkIHJlZ2VuZXJhdGluZyBkZSB0cmFpbiBhbmQgdGVzdCBzZXRzLCBqdXN0IHVuY29tbWVudHMgdGhlIGZvbGxvd2luZyBsaW5lcwojIFdBUk5JTkc6IHRoZXJlIGlzIG5vIGd1YXJhbnRlZSB0aGUgZmlsZXMgc2F2ZWQgY29ycmVzcG9uZCB0byBhcmdlbmNvbi5jc3YuIElmIHVuc3VyZSwganVzdCByZS1ydW4gYnVpbGRfdHJhaW5fdGVzdCgpCmxvYWQoZmlsZT0nZGF0YXNldHMvLnRyYWluX2RhdGFzZXRfa2VyYXMucmQnKQpsb2FkKGZpbGU9J2RhdGFzZXRzLy50ZXN0X2RhdGFzZXRfa2VyYXMucmQnKQpkYXRhc2V0czwtbGlzdCgpCmRhdGFzZXRzJHRyYWluPC10cmFpbl9kYXRhc2V0X2tlcmFzCmRhdGFzZXRzJHRlc3Q8LXRlc3RfZGF0YXNldF9rZXJhcwoKIyMjIEZ1bmN0aW9uIERlZmluaXRpb25zICMjIyMKZ2V0X3ByZWRpY3Rpb25zIDwtIGZ1bmN0aW9uKG1vZGVsLCB0ZXN0X2RhdGFzZXRfeCx0aHJlc2hvbGQ9MC41KSB7CiAgcHJlZHNwcm9iczwtbW9kZWwgJT4lIHByZWRpY3QodGVzdF9kYXRhc2V0X3gsIGJhdGNoX3NpemU9MjU2KQogIHByZWRzPC1pZmVsc2UocHJlZHNwcm9icz50aHJlc2hvbGQsMSwwKQogIHJldHVybiAocHJlZHMpCn0KYGBgCgpgYGB7cn0KbW9kZWw8LWtlcmFzOjpsb2FkX21vZGVsX2hkZjUoIm1vZGVscy9jdHUxOS1sc3RtX2VuZGdhbWUtNDAwLTEwX21vZGVsLmg1IikKc3VtbWFyeShtb2RlbCkKcHJlZHM8LWdldF9wcmVkaWN0aW9ucyhtb2RlbCA9IG1vZGVsLHRlc3RfZGF0YXNldF94ID0gIGRhdGFzZXRzJHRlc3QkZW5jb2RlLHRocmVzaG9sZCA9IDAuNSApCmBgYAoKYGBge3J9CnRlc3RfcmVzdWx0czwtZGF0YS5mcmFtZShwcmVkaWN0ZWRfY2xhc3M9cHJlZHMsY2xhc3M9aWZlbHNlKGdyZXBsKCJOb3JtYWwiLGRhdGFzZXRzJHRlc3QkbGFiZWwpICwwLDEpICxkb21haW49ZGF0YXNldHMkdGVzdCRkb21haW4sbGFiZWw9ZGF0YXNldHMkdGVzdCRsYWJlbCkgCiN0ZXN0X3Jlc3VsdHMKY2FyZXQ6OmNvbmZ1c2lvbk1hdHJpeChhcy5mYWN0b3IodGVzdF9yZXN1bHRzJHByZWRpY3RlZF9jbGFzcyksYXMuZmFjdG9yKHRlc3RfcmVzdWx0cyRjbGFzcyksIHBvc2l0aXZlPScxJywgbW9kZT0iZXZlcnl0aGluZyIgKQpgYGAKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CmZwPC0odGVzdF9yZXN1bHRzICU+JSBtdXRhdGUobW9kZWxzaXplPXN0cl9jb3VudChkb21haW4sIi4iKSkgICU+JSAgZmlsdGVyKGNsYXNzID09IDAgJiBwcmVkaWN0ZWRfY2xhc3MgPT0gMSkpCmZuPC0odGVzdF9yZXN1bHRzICU+JSBtdXRhdGUobW9kZWxzaXplPXN0cl9jb3VudChkb21haW4sIi4iKSkgICU+JSAgZmlsdGVyKGNsYXNzID09IDEgJiBwcmVkaWN0ZWRfY2xhc3MgPT0gMCkpCnRwPC0odGVzdF9yZXN1bHRzICU+JSBtdXRhdGUobW9kZWxzaXplPXN0cl9jb3VudChkb21haW4sIi4iKSkgICU+JSAgZmlsdGVyKGNsYXNzID09IDEgJiBwcmVkaWN0ZWRfY2xhc3MgPT0gMSkpCnRuPC0odGVzdF9yZXN1bHRzICU+JSBtdXRhdGUobW9kZWxzaXplPXN0cl9jb3VudChkb21haW4sIi4iKSkgICU+JSAgZmlsdGVyKGNsYXNzID09IDAgJiBwcmVkaWN0ZWRfY2xhc3MgPT0gMCkpCgoKZnBfZG9tYWluPC1mcCRkb21haW4KdHBfZG9tYWluPC10cCRkb21haW4KZm5fZG9tYWluPC1mbiRkb21haW4KdG5fZG9tYWluPC10biRkb21haW4KCgpmcF9oPC1jcmVhdGVfaGlzdG9ncmFtKGZwX2RvbWFpbikKZnBfaCA8LSBmcF9oICsgIGxhYnModGl0bGU9IkNUVTE5IHNlcSBjaGFyIGRpc3RyaWJ1dGlvbiBmb3IgRmFsc2UgUG9zaXRpdmUiKQojZnBfaCA8LSBmcF9oICsgeWxpbSgwLDUwMCkKCnRwX2g8LWNyZWF0ZV9oaXN0b2dyYW0odHBfZG9tYWluKQp0cF9oIDwtIHRwX2ggKyAgbGFicyh0aXRsZT0iQ1RVMTkgc2VxIGNoYXIgZGlzdHJpYnV0aW9uIGZvciBUcnVlIFBvc2l0aXZlIikKI3RwX2ggPC0gdHBfaCArIHlsaW0oMCw1MDApCgpmbl9oPC1jcmVhdGVfaGlzdG9ncmFtKGZuX2RvbWFpbikKZm5faCA8LSBmbl9oICsgIGxhYnModGl0bGU9IkNUVTE5IHNlcSBjaGFyIGRpc3RyaWJ1dGlvbiBmb3IgRmFsc2UgTmVnYXRpdmUiKQp0bl9oPC1jcmVhdGVfaGlzdG9ncmFtKHRuX2RvbWFpbikKdG5faCA8LSB0bl9oICsgIGxhYnModGl0bGU9IkNUVTE5IHNlcSBjaGFyIGRpc3RyaWJ1dGlvbiBmb3IgVHJ1ZSBOZWdhdGl2ZSIpCgpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShmcF9oLHRwX2gsZm5faCx0bl9oLG5jb2w9MSkKI2xpYnJhcnkoc2NhbGVzKQojdHBfaCArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEwMDApLG9vYiA9IHJlc2NhbGVfbm9uZSkKI2ZwX2ggKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMDAwKSxvb2IgPSByZXNjYWxlX25vbmUpCmBgYAoKYGBge3J9CmZwJHR5cGU8LSJmcCIKdHAkdHlwZTwtInRwIgp0biR0eXBlPC0idG4iCmZuJHR5cGU8LSJmbiIKCnBsb3Q8LXJiaW5kKGZwLHRwLHRuLGZuKSAlPiUKICBnZ3Bsb3QoKSsKICBnZW9tX2JveHBsb3QoYWVzKHg9dHlwZSx5PW1vZGVsc2l6ZSksZmlsbD0nb3JhbmdlJykgKwogIHlsaW0oMCw1MDApKwogIHRoZW1lX2J3KCkKcGxvdApnZ3Bsb3RseShwbG90KQpgYGAKCiMjICBwY2EgMkQgcHJveWVjdGlvbgpgYGB7cn0Kc291cmNlKCJwcmVwcm9jZXNzLlIiKQpsaWJyYXJ5KGFiaW5kKQogIHRwIDwtIHRwICU+JSBzYW1wbGVfbigxMDAwKQogIGZwX3Rva2VuaXplZD10b2tlbml6ZShhcy5tYXRyaXgoZnAkZG9tYWluKSxmcCRsYWJlbCxtYXhsZW4gPSAxMDApCiAgdHBfdG9rZW5pemVkPXRva2VuaXplKGFzLm1hdHJpeCh0cCRkb21haW4pLHRwJGxhYmVsLG1heGxlbiA9IDEwMCkKICBmbl90b2tlbml6ZWQ9dG9rZW5pemUoYXMubWF0cml4KGZuJGRvbWFpbiksZm4kbGFiZWwsbWF4bGVuID0gMTAwKQogIHRuX3Rva2VuaXplZD10b2tlbml6ZShhcy5tYXRyaXgodG4kZG9tYWluKSx0biRsYWJlbCxtYXhsZW4gPSAxMDApCiAgCiAgCiAgCiAgZnBfdG9rZW5pemVkJHJlczwtcmVwKCJGUCIsIGxlbmd0aChmcF90b2tlbml6ZWQkZG9tYWluKSkKICB0cF90b2tlbml6ZWQkcmVzPC1yZXAoIlRQIiwgbGVuZ3RoKHRwX3Rva2VuaXplZCRkb21haW4pKQogIAogIGZuX3Rva2VuaXplZCRyZXM8LXJlcCgiRk4iLCBsZW5ndGgoZm5fdG9rZW5pemVkJGRvbWFpbikpCiAgdG5fdG9rZW5pemVkJHJlczwtcmVwKCJUTiIsIGxlbmd0aCh0bl90b2tlbml6ZWQkZG9tYWluKSkKICAKICAKICBtYWx3YXJlX3Jlc3VsdHM9bGlzdCgpCiAgbWFsd2FyZV9yZXN1bHRzJGVuY29kZTwtYWJpbmQoZnBfdG9rZW5pemVkJGVuY29kZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cF90b2tlbml6ZWQkZW5jb2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZuX3Rva2VuaXplZCRlbmNvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG5fdG9rZW5pemVkJGVuY29kZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxvbmc9MSkKICBtYWx3YXJlX3Jlc3VsdHMkZG9tYWluPC1jKGZwX3Rva2VuaXplZCRkb21haW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cF90b2tlbml6ZWQkZG9tYWluLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm5fdG9rZW5pemVkJGRvbWFpbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRuX3Rva2VuaXplZCRkb21haW4pCiAgICAgICAgICAgICAgICAgICAgICAKICBtYWx3YXJlX3Jlc3VsdHMkcmVzPC1jKGZwX3Rva2VuaXplZCRyZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICB0cF90b2tlbml6ZWQkcmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgZm5fdG9rZW5pemVkJHJlcywKICAgICAgICAgICAgICAgICAgICAgICAgIHRuX3Rva2VuaXplZCRyZXMKICAgICAgICAgICAgICAgICAgICAgICAgICkKICBtYWx3YXJlX3Jlc3VsdHMkbGFiZWw8LWMoYXMuY2hhcmFjdGVyKGZwX3Rva2VuaXplZCRsYWJlbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3Rlcih0cF90b2tlbml6ZWQkbGFiZWwpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoZm5fdG9rZW5pemVkJGxhYmVsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKHRuX3Rva2VuaXplZCRsYWJlbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAKICAjbnJvdyhtYWx3YXJlX3Jlc3VsdHMkZW5jb2RlKQogICNsZW5ndGgobWFsd2FyZV9yZXN1bHRzJGxhYmVsKQogICNsZW5ndGgobWFsd2FyZV9yZXN1bHRzJGRvbWFpbikKICAKICBwY2E9cHJjb21wKG1hbHdhcmVfcmVzdWx0cyRlbmNvZGVbLDE6MjBdLGNlbnRlcj1UUlVFLHNjYWxlLj1UUlVFKQogIHBjYV9kYXRhPC1kYXRhLmZyYW1lKHBjYSR4LHJlcz1tYWx3YXJlX3Jlc3VsdHMkcmVzLGxhYmVsPW1hbHdhcmVfcmVzdWx0cyRsYWJlbCxkb21haW49bWFsd2FyZV9yZXN1bHRzJGRvbWFpbikKICMgcGNhX3Bsb3Q8LWdncGxvdChwY2FfZGF0YSAsYWVzKHg9UEMxLHk9UEM0KSkrCiAjICAgZ2VvbV9wb2ludChhZXMoY29sb3I9cmVzLHRleHQ9ZG9tYWluLHNoYXBlPWFzLmZhY3RvcihsYWJlbCkpLGFscGhhPTAuNSkrCiAjICAgdGhlbWVfYncoKQogIAoKcGxvdGx5OjpwbG90X2x5KHBjYV9kYXRhICwgdHlwZT0ic2NhdHRlcjNkIiwgCiAgICAgICAgICAgICAgICB4ID0gflBDMSwgeSA9IH5QQzIsIHogPSB+UEMzLCBjb2xvciA9IH5yZXMsIHN5bWJvbCA9IH5sYWJlbCwKICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoJ2JsdWUnLCAnb3JhbmdlJywicmVkIiwiZ3JlZW4iKSwgCiAgICAgICAgICAgICAgICBvcGFjaXR5PTAuNSwgbWFya2VyID0gbGlzdChzaXplID0gMyksdGV4dCA9IH5kb21haW4pIApgYGAKCg==