librex 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/README.md +3 -5
  2. data/Rakefile +26 -0
  3. data/lib/rex/compat.rb +1 -1
  4. data/lib/rex/exploitation/javascriptosdetect.rb +125 -62
  5. data/lib/rex/file.rb +15 -0
  6. data/lib/rex/io/stream.rb +1 -1
  7. data/lib/rex/parser/nmap_xml.rb +6 -0
  8. data/lib/rex/poly/block.rb +9 -0
  9. data/lib/rex/post/meterpreter/client.rb +0 -8
  10. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +6 -0
  11. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +1 -1
  12. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +49 -35
  13. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +26 -0
  14. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +9 -2
  15. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +630 -0
  16. data/lib/rex/post/meterpreter/packet.rb +3 -1
  17. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +143 -57
  18. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +6 -0
  19. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +9 -3
  20. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +6 -4
  21. data/lib/rex/proto.rb +1 -0
  22. data/lib/rex/proto/dhcp/server.rb +4 -2
  23. data/lib/rex/proto/http/packet.rb +5 -6
  24. data/lib/rex/proto/ntlm.rb +7 -0
  25. data/lib/rex/proto/ntlm.rb.ut.rb +177 -0
  26. data/lib/rex/proto/ntlm/base.rb +326 -0
  27. data/lib/rex/proto/ntlm/constants.rb +74 -0
  28. data/lib/rex/proto/ntlm/crypt.rb +340 -0
  29. data/lib/rex/proto/ntlm/exceptions.rb +9 -0
  30. data/lib/rex/proto/ntlm/message.rb +533 -0
  31. data/lib/rex/proto/ntlm/utils.rb +358 -0
  32. data/lib/rex/proto/smb/client.rb +548 -86
  33. data/lib/rex/proto/smb/client.rb.ut.rb +4 -4
  34. data/lib/rex/proto/smb/constants.rb +7 -24
  35. data/lib/rex/proto/smb/crypt.rb +12 -71
  36. data/lib/rex/proto/smb/exceptions.rb +12 -0
  37. data/lib/rex/proto/smb/simpleclient.rb +17 -5
  38. data/lib/rex/proto/smb/utils.rb +3 -460
  39. data/lib/rex/proto/tftp/server.rb +2 -2
  40. data/lib/rex/script/base.rb +2 -2
  41. data/lib/rex/socket.rb +12 -0
  42. data/lib/rex/socket.rb.ut.rb +31 -10
  43. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +15 -5
  44. data/lib/rex/text.rb +55 -4
  45. data/lib/rex/ui/output.rb +0 -2
  46. data/lib/rex/ui/text/dispatcher_shell.rb +95 -10
  47. data/lib/rex/ui/text/output/buffer.rb +0 -4
  48. data/lib/rex/ui/text/shell.rb +8 -0
  49. data/lib/rex/ui/text/table.rb +21 -1
  50. metadata +15 -19
  51. data/lib/rex/proto/smb/crypt.rb.ut.rb +0 -20
@@ -207,14 +207,6 @@ class Client
207
207
  @@ssl_ctx
208
208
  end
209
209
 
210
- #
211
- # Runs the meterpreter script in the context of a script container
212
- #
213
- def execute_file(file, args)
214
- o = Rex::Script::Meterpreter.new(self, file)
215
- o.run(args)
216
- end
217
-
218
210
  ##
219
211
  #
220
212
  # Accessors
@@ -72,6 +72,12 @@ class Priv < Extension
72
72
  if( response.result == 0 and technique != nil )
73
73
  client.core.use( "stdapi" ) if not client.ext.aliases.include?( "stdapi" )
74
74
  client.sys.config.getprivs
75
+ client.framework.db.report_note(
76
+ :host => client.sock.peerhost,
77
+ :workspace => client.framework.db.workspace,
78
+ :type => "meterpreter.getsystem",
79
+ :data => {:technique => technique}
80
+ ) rescue nil
75
81
  return [ true, technique ]
76
82
  end
77
83
 
@@ -73,7 +73,7 @@ Separator = "\\"
73
73
  # I suck at regex.
74
74
  path =~ /(.*)#{sep}(.*)$/
75
75
 
76
- return $2 || path
76
+ Rex::FileUtils.clean_path($2 || path)
77
77
  end
78
78
 
79
79
  #
@@ -620,7 +620,7 @@ class Def_advapi32
620
620
 
621
621
  railgun.add_function( 'advapi32', 'AccessCheckByType', 'BOOL',[
622
622
  ["PBLOB","pSecurityDescriptor","in"],
623
- ["PBLOB","PrincipalSelfSid","in"],
623
+ ["LPVOID","PrincipalSelfSid","in"],
624
624
  ["DWORD","ClientToken","in"],
625
625
  ["DWORD","DesiredAccess","in"],
626
626
  ["PBLOB","ObjectTypeList","inout"],
@@ -638,7 +638,7 @@ class Def_advapi32
638
638
  ["PCHAR","ObjectTypeName","in"],
639
639
  ["PCHAR","ObjectName","in"],
640
640
  ["PBLOB","SecurityDescriptor","in"],
641
- ["PBLOB","PrincipalSelfSid","in"],
641
+ ["LPVOID","PrincipalSelfSid","in"],
642
642
  ["DWORD","DesiredAccess","in"],
643
643
  ["DWORD","AuditType","in"],
644
644
  ["DWORD","Flags","in"],
@@ -657,7 +657,7 @@ class Def_advapi32
657
657
  ["PWCHAR","ObjectTypeName","in"],
658
658
  ["PWCHAR","ObjectName","in"],
659
659
  ["PBLOB","SecurityDescriptor","in"],
660
- ["PBLOB","PrincipalSelfSid","in"],
660
+ ["LPVOID","PrincipalSelfSid","in"],
661
661
  ["DWORD","DesiredAccess","in"],
662
662
  ["DWORD","AuditType","in"],
663
663
  ["DWORD","Flags","in"],
@@ -672,7 +672,7 @@ class Def_advapi32
672
672
 
673
673
  railgun.add_function( 'advapi32', 'AccessCheckByTypeResultList', 'BOOL',[
674
674
  ["PBLOB","pSecurityDescriptor","in"],
675
- ["PBLOB","PrincipalSelfSid","in"],
675
+ ["LPVOID","PrincipalSelfSid","in"],
676
676
  ["DWORD","ClientToken","in"],
677
677
  ["DWORD","DesiredAccess","in"],
678
678
  ["PBLOB","ObjectTypeList","inout"],
@@ -690,7 +690,7 @@ class Def_advapi32
690
690
  ["PCHAR","ObjectTypeName","in"],
691
691
  ["PCHAR","ObjectName","in"],
692
692
  ["PBLOB","SecurityDescriptor","in"],
693
- ["PBLOB","PrincipalSelfSid","in"],
693
+ ["LPVOID","PrincipalSelfSid","in"],
694
694
  ["DWORD","DesiredAccess","in"],
695
695
  ["DWORD","AuditType","in"],
696
696
  ["DWORD","Flags","in"],
@@ -710,7 +710,7 @@ class Def_advapi32
710
710
  ["PCHAR","ObjectTypeName","in"],
711
711
  ["PCHAR","ObjectName","in"],
712
712
  ["PBLOB","SecurityDescriptor","in"],
713
- ["PBLOB","PrincipalSelfSid","in"],
713
+ ["LPVOID","PrincipalSelfSid","in"],
714
714
  ["DWORD","DesiredAccess","in"],
715
715
  ["DWORD","AuditType","in"],
716
716
  ["DWORD","Flags","in"],
@@ -730,7 +730,7 @@ class Def_advapi32
730
730
  ["PWCHAR","ObjectTypeName","in"],
731
731
  ["PWCHAR","ObjectName","in"],
732
732
  ["PBLOB","SecurityDescriptor","in"],
733
- ["PBLOB","PrincipalSelfSid","in"],
733
+ ["LPVOID","PrincipalSelfSid","in"],
734
734
  ["DWORD","DesiredAccess","in"],
735
735
  ["DWORD","AuditType","in"],
736
736
  ["DWORD","Flags","in"],
@@ -749,7 +749,7 @@ class Def_advapi32
749
749
  ["PWCHAR","ObjectTypeName","in"],
750
750
  ["PWCHAR","ObjectName","in"],
751
751
  ["PBLOB","SecurityDescriptor","in"],
752
- ["PBLOB","PrincipalSelfSid","in"],
752
+ ["LPVOID","PrincipalSelfSid","in"],
753
753
  ["DWORD","DesiredAccess","in"],
754
754
  ["DWORD","AuditType","in"],
755
755
  ["DWORD","Flags","in"],
@@ -766,7 +766,7 @@ class Def_advapi32
766
766
  ["PBLOB","pAcl","inout"],
767
767
  ["DWORD","dwAceRevision","in"],
768
768
  ["DWORD","AccessMask","in"],
769
- ["PBLOB","pSid","in"],
769
+ ["LPVOID","pSid","in"],
770
770
  ])
771
771
 
772
772
  railgun.add_function( 'advapi32', 'AddAccessAllowedAceEx', 'BOOL',[
@@ -774,7 +774,7 @@ class Def_advapi32
774
774
  ["DWORD","dwAceRevision","in"],
775
775
  ["DWORD","AceFlags","in"],
776
776
  ["DWORD","AccessMask","in"],
777
- ["PBLOB","pSid","in"],
777
+ ["LPVOID","pSid","in"],
778
778
  ])
779
779
 
780
780
  railgun.add_function( 'advapi32', 'AddAccessAllowedObjectAce', 'BOOL',[
@@ -784,14 +784,14 @@ class Def_advapi32
784
784
  ["DWORD","AccessMask","in"],
785
785
  ["PBLOB","ObjectTypeGuid","in"],
786
786
  ["PBLOB","InheritedObjectTypeGuid","in"],
787
- ["PBLOB","pSid","in"],
787
+ ["LPVOID","pSid","in"],
788
788
  ])
789
789
 
790
790
  railgun.add_function( 'advapi32', 'AddAccessDeniedAce', 'BOOL',[
791
791
  ["PBLOB","pAcl","inout"],
792
792
  ["DWORD","dwAceRevision","in"],
793
793
  ["DWORD","AccessMask","in"],
794
- ["PBLOB","pSid","in"],
794
+ ["LPVOID","pSid","in"],
795
795
  ])
796
796
 
797
797
  railgun.add_function( 'advapi32', 'AddAccessDeniedAceEx', 'BOOL',[
@@ -799,7 +799,7 @@ class Def_advapi32
799
799
  ["DWORD","dwAceRevision","in"],
800
800
  ["DWORD","AceFlags","in"],
801
801
  ["DWORD","AccessMask","in"],
802
- ["PBLOB","pSid","in"],
802
+ ["LPVOID","pSid","in"],
803
803
  ])
804
804
 
805
805
  railgun.add_function( 'advapi32', 'AddAccessDeniedObjectAce', 'BOOL',[
@@ -809,7 +809,7 @@ class Def_advapi32
809
809
  ["DWORD","AccessMask","in"],
810
810
  ["PBLOB","ObjectTypeGuid","in"],
811
811
  ["PBLOB","InheritedObjectTypeGuid","in"],
812
- ["PBLOB","pSid","in"],
812
+ ["LPVOID","pSid","in"],
813
813
  ])
814
814
 
815
815
  railgun.add_function( 'advapi32', 'AddAce', 'BOOL',[
@@ -824,7 +824,7 @@ class Def_advapi32
824
824
  ["PBLOB","pAcl","inout"],
825
825
  ["DWORD","dwAceRevision","in"],
826
826
  ["DWORD","dwAccessMask","in"],
827
- ["PBLOB","pSid","in"],
827
+ ["LPVOID","pSid","in"],
828
828
  ["BOOL","bAuditSuccess","in"],
829
829
  ["BOOL","bAuditFailure","in"],
830
830
  ])
@@ -834,7 +834,7 @@ class Def_advapi32
834
834
  ["DWORD","dwAceRevision","in"],
835
835
  ["DWORD","AceFlags","in"],
836
836
  ["DWORD","dwAccessMask","in"],
837
- ["PBLOB","pSid","in"],
837
+ ["LPVOID","pSid","in"],
838
838
  ["BOOL","bAuditSuccess","in"],
839
839
  ["BOOL","bAuditFailure","in"],
840
840
  ])
@@ -846,7 +846,7 @@ class Def_advapi32
846
846
  ["DWORD","AccessMask","in"],
847
847
  ["PBLOB","ObjectTypeGuid","in"],
848
848
  ["PBLOB","InheritedObjectTypeGuid","in"],
849
- ["PBLOB","pSid","in"],
849
+ ["LPVOID","pSid","in"],
850
850
  ["BOOL","bAuditSuccess","in"],
851
851
  ["BOOL","bAuditFailure","in"],
852
852
  ])
@@ -880,7 +880,7 @@ class Def_advapi32
880
880
  ["DWORD","nSubAuthority5","in"],
881
881
  ["DWORD","nSubAuthority6","in"],
882
882
  ["DWORD","nSubAuthority7","in"],
883
- ["PBLOB","pSid","out"],
883
+ ["PDWORD","pSid","out"],
884
884
  ])
885
885
 
886
886
  railgun.add_function( 'advapi32', 'AllocateLocallyUniqueId', 'BOOL',[
@@ -940,10 +940,20 @@ class Def_advapi32
940
940
  ["PBLOB","GenericMapping","in"],
941
941
  ])
942
942
 
943
+ railgun.add_function( 'advapi32', 'ConvertStringSidToSidA', 'BOOL',[
944
+ ["PCHAR","StringSid","in"],
945
+ ["PDWORD","pSid","out"],
946
+ ])
947
+
948
+ railgun.add_function( 'advapi32', 'ConvertStringSidToSidW', 'BOOL',[
949
+ ["PWCHAR","StringSid","in"],
950
+ ["PDWORD","pSid","out"],
951
+ ])
952
+
943
953
  railgun.add_function( 'advapi32', 'CopySid', 'BOOL',[
944
954
  ["DWORD","nDestinationSidLength","in"],
945
955
  ["PBLOB","pDestinationSid","out"],
946
- ["PBLOB","pSourceSid","in"],
956
+ ["LPVOID","pSourceSid","in"],
947
957
  ])
948
958
 
949
959
  railgun.add_function( 'advapi32', 'CreatePrivateObjectSecurity', 'BOOL',[
@@ -1098,19 +1108,19 @@ class Def_advapi32
1098
1108
  ])
1099
1109
 
1100
1110
  railgun.add_function( 'advapi32', 'EqualDomainSid', 'BOOL',[
1101
- ["PBLOB","pSid1","in"],
1102
- ["PBLOB","pSid2","in"],
1111
+ ["LPVOID","pSid1","in"],
1112
+ ["LPVOID","pSid2","in"],
1103
1113
  ["PBLOB","pfEqual","out"],
1104
1114
  ])
1105
1115
 
1106
1116
  railgun.add_function( 'advapi32', 'EqualPrefixSid', 'BOOL',[
1107
- ["PBLOB","pSid1","in"],
1108
- ["PBLOB","pSid2","in"],
1117
+ ["LPVOID","pSid1","in"],
1118
+ ["LPVOID","pSid2","in"],
1109
1119
  ])
1110
1120
 
1111
1121
  railgun.add_function( 'advapi32', 'EqualSid', 'BOOL',[
1112
- ["PBLOB","pSid1","in"],
1113
- ["PBLOB","pSid2","in"],
1122
+ ["LPVOID","pSid1","in"],
1123
+ ["LPVOID","pSid2","in"],
1114
1124
  ])
1115
1125
 
1116
1126
  railgun.add_function( 'advapi32', 'FileEncryptionStatusA', 'BOOL',[
@@ -1128,6 +1138,10 @@ class Def_advapi32
1128
1138
  ["PBLOB","pAce","out"],
1129
1139
  ])
1130
1140
 
1141
+ railgun.add_function( 'advapi32', 'FreeSid', 'LPVOID',[
1142
+ ["LPVOID","pSid","in"],
1143
+ ])
1144
+
1131
1145
  railgun.add_function( 'advapi32', 'GetAce', 'BOOL',[
1132
1146
  ["PBLOB","pAcl","in"],
1133
1147
  ["DWORD","dwAceIndex","in"],
@@ -1182,7 +1196,7 @@ class Def_advapi32
1182
1196
  ])
1183
1197
 
1184
1198
  railgun.add_function( 'advapi32', 'GetLengthSid', 'DWORD',[
1185
- ["PBLOB","pSid","in"],
1199
+ ["LPVOID","pSid","in"],
1186
1200
  ])
1187
1201
 
1188
1202
  railgun.add_function( 'advapi32', 'GetNumberOfEventLogRecords', 'BOOL',[
@@ -1267,7 +1281,7 @@ class Def_advapi32
1267
1281
  ])
1268
1282
 
1269
1283
  railgun.add_function( 'advapi32', 'GetWindowsAccountDomainSid', 'BOOL',[
1270
- ["PBLOB","pSid","in"],
1284
+ ["LPVOID","pSid","in"],
1271
1285
  ["PBLOB","pDomainSid","out"],
1272
1286
  ["PDWORD","cbDomainSid","inout"],
1273
1287
  ])
@@ -1327,11 +1341,11 @@ class Def_advapi32
1327
1341
  ])
1328
1342
 
1329
1343
  railgun.add_function( 'advapi32', 'IsValidSid', 'BOOL',[
1330
- ["PBLOB","pSid","in"],
1344
+ ["LPVOID","pSid","in"],
1331
1345
  ])
1332
1346
 
1333
1347
  railgun.add_function( 'advapi32', 'IsWellKnownSid', 'BOOL',[
1334
- ["PBLOB","pSid","in"],
1348
+ ["LPVOID","pSid","in"],
1335
1349
  ["DWORD","WellKnownSidType","in"],
1336
1350
  ])
1337
1351
 
@@ -1351,7 +1365,7 @@ class Def_advapi32
1351
1365
  ["DWORD","dwLogonType","in"],
1352
1366
  ["DWORD","dwLogonProvider","in"],
1353
1367
  ["PDWORD","phToken","out"],
1354
- ["PBLOB","ppLogonSid","out"],
1368
+ ["PDWORD","ppLogonSid","out"],
1355
1369
  ["PBLOB","ppProfileBuffer","out"],
1356
1370
  ["PDWORD","pdwProfileLength","out"],
1357
1371
  ["PBLOB","pQuotaLimits","out"],
@@ -1364,7 +1378,7 @@ class Def_advapi32
1364
1378
  ["DWORD","dwLogonType","in"],
1365
1379
  ["DWORD","dwLogonProvider","in"],
1366
1380
  ["PDWORD","phToken","out"],
1367
- ["PBLOB","ppLogonSid","out"],
1381
+ ["PDWORD","ppLogonSid","out"],
1368
1382
  ["PBLOB","ppProfileBuffer","out"],
1369
1383
  ["PDWORD","pdwProfileLength","out"],
1370
1384
  ["PBLOB","pQuotaLimits","out"],
@@ -1401,7 +1415,7 @@ class Def_advapi32
1401
1415
 
1402
1416
  railgun.add_function( 'advapi32', 'LookupAccountSidA', 'BOOL',[
1403
1417
  ["PCHAR","lpSystemName","in"],
1404
- ["PBLOB","Sid","in"],
1418
+ ["LPVOID","Sid","in"],
1405
1419
  ["PCHAR","Name","out"],
1406
1420
  ["PDWORD","cchName","inout"],
1407
1421
  ["PCHAR","ReferencedDomainName","out"],
@@ -1411,7 +1425,7 @@ class Def_advapi32
1411
1425
 
1412
1426
  railgun.add_function( 'advapi32', 'LookupAccountSidW', 'BOOL',[
1413
1427
  ["PWCHAR","lpSystemName","in"],
1414
- ["PBLOB","Sid","in"],
1428
+ ["LPVOID","Sid","in"],
1415
1429
  ["PWCHAR","Name","out"],
1416
1430
  ["PDWORD","cchName","inout"],
1417
1431
  ["PWCHAR","ReferencedDomainName","out"],
@@ -1676,7 +1690,7 @@ class Def_advapi32
1676
1690
  ["WORD","wType","in"],
1677
1691
  ["WORD","wCategory","in"],
1678
1692
  ["DWORD","dwEventID","in"],
1679
- ["PBLOB","lpUserSid","in"],
1693
+ ["LPVOID","lpUserSid","in"],
1680
1694
  ["WORD","wNumStrings","in"],
1681
1695
  ["DWORD","dwDataSize","in"],
1682
1696
  ["PBLOB","lpStrings","in"],
@@ -1688,7 +1702,7 @@ class Def_advapi32
1688
1702
  ["WORD","wType","in"],
1689
1703
  ["WORD","wCategory","in"],
1690
1704
  ["DWORD","dwEventID","in"],
1691
- ["PBLOB","lpUserSid","in"],
1705
+ ["LPVOID","lpUserSid","in"],
1692
1706
  ["WORD","wNumStrings","in"],
1693
1707
  ["DWORD","dwDataSize","in"],
1694
1708
  ["PBLOB","lpStrings","in"],
@@ -0,0 +1,26 @@
1
+ module Rex
2
+ module Post
3
+ module Meterpreter
4
+ module Extensions
5
+ module Stdapi
6
+ module Railgun
7
+ module Def
8
+
9
+ class Def_netapi32
10
+
11
+ def self.add_imports(railgun)
12
+
13
+ railgun.add_dll('netapi32')
14
+
15
+ railgun.add_function( 'netapi32', 'NetUserDel', 'DWORD',[
16
+ ["PWCHAR","servername","in"],
17
+ ["PWCHAR","username","in"],
18
+ ])
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end; end; end; end; end; end; end
25
+
26
+
@@ -30,6 +30,7 @@ require 'pp'
30
30
  require 'enumerator'
31
31
  require 'rex/post/meterpreter/extensions/stdapi/railgun/api_constants'
32
32
  require 'rex/post/meterpreter/extensions/stdapi/railgun/tlv'
33
+ require 'rex/post/meterpreter/extensions/stdapi/railgun/util'
33
34
  require 'rex/post/meterpreter/extensions/stdapi/railgun/model'
34
35
  require 'rex/post/meterpreter/extensions/stdapi/railgun/multicall'
35
36
 
@@ -56,6 +57,9 @@ class Railgun
56
57
 
57
58
  # Load the multi-caller
58
59
  @multicaller = MultiCaller.new( @client, self, @win_consts )
60
+
61
+ # Load utility class
62
+ @util = Util.new( self, @client.platform )
59
63
  end
60
64
 
61
65
  # read data from a memory address on the host (useful for working with LPVOID parameters)
@@ -140,6 +144,9 @@ class Railgun
140
144
  when 'iphlpapi'
141
145
  require 'rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi'
142
146
  Def::Def_iphlpapi.add_imports(self)
147
+ when 'netapi32'
148
+ require 'rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32'
149
+ Def::Def_netapi32.add_imports(self)
143
150
  when 'advapi32'
144
151
  require 'rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32'
145
152
  Def::Def_advapi32.add_imports(self)
@@ -189,8 +196,8 @@ class Railgun
189
196
  @multicaller.call(functions)
190
197
  end
191
198
 
192
- attr_accessor :client, :dll, :multicaller, :win_consts
199
+ attr_accessor :client, :dll, :multicaller, :win_consts, :util
193
200
 
194
201
  end
195
202
 
196
- end; end; end; end; end; end
203
+ end; end; end; end; end; end
@@ -0,0 +1,630 @@
1
+ require 'rex/post/meterpreter/extensions/stdapi/railgun/model'
2
+
3
+ module Rex
4
+ module Post
5
+ module Meterpreter
6
+ module Extensions
7
+ module Stdapi
8
+ module Railgun
9
+ class Util
10
+
11
+ # Bring in some useful string manipulation utility functions
12
+ include DLLHelper
13
+
14
+ # Data type size info: http://msdn.microsoft.com/en-us/library/s3f49ktz(v=vs.80).aspx
15
+ PRIMITIVE_TYPE_SIZES = {
16
+ :int => 4,
17
+ :__int8 => 1,
18
+ :__int16 => 2,
19
+ :__int32 => 4,
20
+ :__int64 => 8,
21
+ :bool => 1,
22
+ :char => 1,
23
+ :short => 2,
24
+ :long => 4,
25
+ :long_long => 8,
26
+ :float => 4,
27
+ :double => 8,
28
+ :long_double => 8,
29
+ :wchar_t => 2,
30
+ }
31
+
32
+ # Maps a data type to its corresponding primitive or special type :pointer
33
+ # Note, primitive types are mapped to themselves
34
+ # typedef info: http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx
35
+ TYPE_DEFINITIONS = {
36
+ ##
37
+ # Primitives
38
+ ##
39
+ :int => :int,
40
+ :__int8 => :__int8,
41
+ :__int16 => :__int16,
42
+ :__int32 => :__int32,
43
+ :__int64 => :__int64,
44
+ :bool => :bool,
45
+ :char => :char,
46
+ :short => :short,
47
+ :long => :long,
48
+ :long_long => :long_long,
49
+ :float => :float,
50
+ :double => :double,
51
+ :long_double => :long_double,
52
+ :wchar_t => :wchar_t,
53
+ ##
54
+ # Non-pointers
55
+ ##
56
+ #typedef WORD ATOM;
57
+ :ATOM => :short,
58
+ #typedef int BOOL;
59
+ :BOOL => :int,
60
+ #typedef BYTE BOOLEAN;
61
+ :BOOLEAN => :char,
62
+ #typedef unsigned char BYTE;
63
+ :BYTE => :char,
64
+ #typedef char CHAR;
65
+ :CHAR => :char,
66
+ #typedef DWORD COLORREF;
67
+ :COLORREF => :long,
68
+ #typedef unsigned long DWORD;
69
+ :DWORD => :long,
70
+ #typedef unsigned int DWORD32;
71
+ :DWORD32 => :int,
72
+ #typedef unsigned __int64 DWORD64;
73
+ :DWORD64 => :__int64,
74
+ #typedef float FLOAT;
75
+ :FLOAT => :float,
76
+ #typedef int HFILE;
77
+ :HFILE => :int,
78
+ #typedef LONG HRESULT;
79
+ :HRESULT => :long,
80
+ #typedef int INT;
81
+ :INT => :int,
82
+ #typedef signed int INT32;
83
+ :INT32 => :int,
84
+ #typedef signed __int64 INT64;
85
+ :INT64 => :__int64,
86
+ #typedef WORD LANGID;
87
+ :LANGID => :short,
88
+ #typedef DWORD LCID;
89
+ :LCID => :long,
90
+ #typedef DWORD LCTYPE;
91
+ :LCTYPE => :long,
92
+ #typedef DWORD LGRPID;
93
+ :LGRPID => :long,
94
+ #typedef long LONG;
95
+ :LONG => :long,
96
+ #typedef signed int LONG32;
97
+ :LONG32 => :int,
98
+ #typedef __int64 LONG64;
99
+ :LONG64 => :__int64,
100
+ #typedef PDWORD PLCID;
101
+ :PLCID => :pointer,
102
+ #typedef LPVOID SC_LOCK;
103
+ :SC_LOCK => :pointer,
104
+ #typedef short SHORT;
105
+ :SHORT => :short,
106
+ #typedef unsigned char UCHAR;
107
+ :UCHAR => :char,
108
+ #typedef unsigned int UINT;
109
+ :UINT => :int,
110
+ #typedef unsigned int UINT32;
111
+ :UINT32 => :int,
112
+ #typedef unsigned long ULONG;
113
+ :ULONG => :long,
114
+ #typedef unsigned int ULONG32;
115
+ :ULONG32 => :int,
116
+ #typedef unsigned __int64 ULONG64;
117
+ :ULONG64 => :__int64,
118
+ #typedef unsigned short USHORT;
119
+ :USHORT => :short,
120
+ #typedef wchar_t WCHAR;
121
+ :WCHAR => :wchar_t,
122
+ #typedef unsigned short WORD;
123
+ :WORD => :short,
124
+ ##
125
+ # Pointers declared with *
126
+ ##
127
+ #typedef DWORD* LPCOLORREF;
128
+ :LPCOLORREF => :pointer,
129
+ #typedef void* LPCVOID;
130
+ :LPCVOID => :pointer,
131
+ #typedef WCHAR* LPCWSTR;
132
+ :LPCWSTR => :pointer,
133
+ #typedef DWORD* LPDWORD;
134
+ :LPDWORD => :pointer,
135
+ #typedef HANDLE* LPHANDLE;
136
+ :LPHANDLE => :pointer,
137
+ #typedef int* LPINT;
138
+ :LPINT => :pointer,
139
+ #typedef long* LPLONG;
140
+ :LPLONG => :pointer,
141
+ #typedef CHAR* LPSTR;
142
+ :LPSTR => :pointer,
143
+ #typedef void* LPVOID;
144
+ :LPVOID => :pointer,
145
+ #typedef WORD* LPWORD;
146
+ :LPWORD => :pointer,
147
+ #typedef WCHAR* LPWSTR;
148
+ :LPWSTR => :pointer,
149
+ #typedef BOOL* PBOOL;
150
+ :PBOOL => :pointer,
151
+ #typedef BOOLEAN* PBOOLEAN;
152
+ :PBOOLEAN => :pointer,
153
+ #typedef BYTE* PBYTE;
154
+ :PBYTE => :pointer,
155
+ #typedef CHAR* PCHAR;
156
+ :PCHAR => :pointer,
157
+ #typedef CHAR* PCSTR;
158
+ :PCSTR => :pointer,
159
+ #typedef WCHAR* PCWSTR;
160
+ :PCWSTR => :pointer,
161
+ #typedef DWORD* PDWORD;
162
+ :PDWORD => :pointer,
163
+ #typedef DWORDLONG* PDWORDLONG;
164
+ :PDWORDLONG => :pointer,
165
+ #typedef DWORD_PTR* PDWORD_PTR;
166
+ :PDWORD_PTR => :pointer,
167
+ #typedef DWORD32* PDWORD32;
168
+ :PDWORD32 => :pointer,
169
+ #typedef DWORD64* PDWORD64;
170
+ :PDWORD64 => :pointer,
171
+ #typedef FLOAT* PFLOAT;
172
+ :PFLOAT => :pointer,
173
+ #typedef HANDLE* PHANDLE;
174
+ :PHANDLE => :pointer,
175
+ #typedef HKEY* PHKEY;
176
+ :PHKEY => :pointer,
177
+ #typedef int* PINT;
178
+ :PINT => :pointer,
179
+ #typedef INT_PTR* PINT_PTR;
180
+ :PINT_PTR => :pointer,
181
+ #typedef INT32* PINT32;
182
+ :PINT32 => :pointer,
183
+ #typedef INT64* PINT64;
184
+ :PINT64 => :pointer,
185
+ #typedef LONG* PLONG;
186
+ :PLONG => :pointer,
187
+ #typedef LONGLONG* PLONGLONG;
188
+ :PLONGLONG => :pointer,
189
+ #typedef LONG_PTR* PLONG_PTR;
190
+ :PLONG_PTR => :pointer,
191
+ #typedef LONG32* PLONG32;
192
+ :PLONG32 => :pointer,
193
+ #typedef LONG64* PLONG64;
194
+ :PLONG64 => :pointer,
195
+ #typedef SHORT* PSHORT;
196
+ :PSHORT => :pointer,
197
+ #typedef SIZE_T* PSIZE_T;
198
+ :PSIZE_T => :pointer,
199
+ #typedef SSIZE_T* PSSIZE_T;
200
+ :PSSIZE_T => :pointer,
201
+ #typedef CHAR* PSTR;
202
+ :PSTR => :pointer,
203
+ #typedef TBYTE* PTBYTE;
204
+ :PTBYTE => :pointer,
205
+ #typedef TCHAR* PTCHAR;
206
+ :PTCHAR => :pointer,
207
+ #typedef UCHAR* PUCHAR;
208
+ :PUCHAR => :pointer,
209
+ #typedef UINT* PUINT;
210
+ :PUINT => :pointer,
211
+ #typedef UINT_PTR* PUINT_PTR;
212
+ :PUINT_PTR => :pointer,
213
+ #typedef UINT32* PUINT32;
214
+ :PUINT32 => :pointer,
215
+ #typedef UINT64* PUINT64;
216
+ :PUINT64 => :pointer,
217
+ #typedef ULONG* PULONG;
218
+ :PULONG => :pointer,
219
+ #typedef ULONGLONG* PULONGLONG;
220
+ :PULONGLONG => :pointer,
221
+ #typedef ULONG_PTR* PULONG_PTR;
222
+ :PULONG_PTR => :pointer,
223
+ #typedef ULONG32* PULONG32;
224
+ :PULONG32 => :pointer,
225
+ #typedef ULONG64* PULONG64;
226
+ :PULONG64 => :pointer,
227
+ #typedef USHORT* PUSHORT;
228
+ :PUSHORT => :pointer,
229
+ #typedef void* PVOID;
230
+ :PVOID => :pointer,
231
+ #typedef WCHAR* PWCHAR;
232
+ :PWCHAR => :pointer,
233
+ #typedef WORD* PWORD;
234
+ :PWORD => :pointer,
235
+ #typedef WCHAR* PWSTR;
236
+ :PWSTR => :pointer,
237
+ #typedef HANDLE HACCEL;
238
+ :HACCEL => :pointer,
239
+ ##
240
+ # Handles
241
+ ##
242
+ #typedef PVOID HANDLE;
243
+ :HANDLE => :pointer,
244
+ #typedef HANDLE HBITMAP;
245
+ :HBITMAP => :pointer,
246
+ #typedef HANDLE HBRUSH;
247
+ :HBRUSH => :pointer,
248
+ #typedef HANDLE HCOLORSPACE;
249
+ :HCOLORSPACE => :pointer,
250
+ #typedef HANDLE HCONV;
251
+ :HCONV => :pointer,
252
+ #typedef HANDLE HCONVLIST;
253
+ :HCONVLIST => :pointer,
254
+ #typedef HANDLE HDC;
255
+ :HDC => :pointer,
256
+ #typedef HANDLE HDDEDATA;
257
+ :HDDEDATA => :pointer,
258
+ #typedef HANDLE HDESK;
259
+ :HDESK => :pointer,
260
+ #typedef HANDLE HDROP;
261
+ :HDROP => :pointer,
262
+ #typedef HANDLE HDWP;
263
+ :HDWP => :pointer,
264
+ #typedef HANDLE HENHMETAFILE;
265
+ :HENHMETAFILE => :pointer,
266
+ #typedef HANDLE HFONT;
267
+ :HFONT => :pointer,
268
+ #typedef HANDLE HGDIOBJ;
269
+ :HGDIOBJ => :pointer,
270
+ #typedef HANDLE HGLOBAL;
271
+ :HGLOBAL => :pointer,
272
+ #typedef HANDLE HHOOK;
273
+ :HHOOK => :pointer,
274
+ #typedef HANDLE HICON;
275
+ :HICON => :pointer,
276
+ #typedef HANDLE HINSTANCE;
277
+ :HINSTANCE => :pointer,
278
+ #typedef HANDLE HKEY;
279
+ :HKEY => :pointer,
280
+ #typedef HANDLE HKL;
281
+ :HKL => :pointer,
282
+ #typedef HANDLE HLOCAL;
283
+ :HLOCAL => :pointer,
284
+ #typedef HANDLE HMENU;
285
+ :HMENU => :pointer,
286
+ #typedef HANDLE HMETAFILE;
287
+ :HMETAFILE => :pointer,
288
+ #typedef HANDLE HPALETTE;
289
+ :HPALETTE => :pointer,
290
+ #typedef HANDLE HPEN;
291
+ :HPEN => :pointer,
292
+ #typedef HANDLE HRGN;
293
+ :HRGN => :pointer,
294
+ #typedef HANDLE HRSRC;
295
+ :HRSRC => :pointer,
296
+ #typedef HANDLE HSZ;
297
+ :HSZ => :pointer,
298
+ #typedef HANDLE WINSTA;
299
+ :WINSTA => :pointer,
300
+ #typedef HANDLE HWND;
301
+ :HWND => :pointer,
302
+ #typedef HANDLE SC_HANDLE;
303
+ :SC_HANDLE => :pointer,
304
+ #typedef HANDLE SERVICE_STATUS_HANDLE;
305
+ :SERVICE_STATUS_HANDLE => :pointer,
306
+ }
307
+
308
+ # param 'railgun' is a Railgun instance.
309
+ # param 'platform' is a value like client.platform
310
+ def initialize(railgun, platform)
311
+ @railgun = railgun
312
+ @is_64bit = is_64bit_platform?(platform)
313
+ end
314
+
315
+ # Given a packed pointer, unpacks it according to architecture
316
+ def unpack_pointer(packed_pointer)
317
+ if is_64bit
318
+ # XXX: Only works if attacker and victim are like-endianed
319
+ packed_pointer.unpack('Q')[0]
320
+ else
321
+ packed_pointer.unpack('V')[0]
322
+ end
323
+ end
324
+
325
+ ###
326
+ # Summary: Returns true if pointer will be considered a 'null' pointer
327
+ #
328
+ # If given nil, returns true
329
+ # If given 0, returns true
330
+ # If given a string, if 0 after unpacking, returns true
331
+ # false otherwise
332
+ ##
333
+ def is_null_pointer(pointer)
334
+ if pointer.class == String
335
+ pointer = unpack_pointer(pointer)
336
+ end
337
+
338
+ return pointer.nil? || pointer == 0
339
+ end
340
+
341
+ ###
342
+ # Summary: Reads null-terminated unicode strings from memory.
343
+ #
344
+ # Given a pointer to a null terminated array of WCHARs, return a ruby string
345
+ # Null pointers cause an empty string to be returned
346
+ ##
347
+ def read_wstring(pointer, length = nil)
348
+ # Return an empty string for null pointers
349
+ if is_null_pointer(pointer)
350
+ return ''
351
+ end
352
+
353
+ # If length not provided, use lstrlenW
354
+ if length.nil?
355
+ length = railgun.kernel32.lstrlenW(pointer)['return']
356
+ end
357
+
358
+ # Retrieve the array of characters
359
+ chars = read_array(:WCHAR, length, pointer)
360
+
361
+ # Concatenate the characters and convert to a ruby string
362
+ str = uniz_to_str(chars.join(''))
363
+
364
+ return str
365
+ end
366
+
367
+ ###
368
+ # Summary: Read a given number of bytes from memory or from a provided buffer.
369
+ #
370
+ # If 'buffer' is not provided, read 'size' bytes from the client's memory
371
+ # If 'buffer' is provided, reads 'size' characters from the index of 'address'
372
+ ##
373
+ def memread(address, size, buffer = nil)
374
+ if buffer.nil?
375
+ return railgun.memread(address, size)
376
+ else
377
+ return buffer[address .. (address + size - 1)]
378
+ end
379
+ end
380
+
381
+ # Read and unpack a pointer from the given buffer at a given offset
382
+ def read_pointer(buffer, offset = 0)
383
+ unpack_pointer(buffer[offset, (offset + pointer_size)])
384
+ end
385
+
386
+ # Reads data structures and several windows data types
387
+ def read_data(type, position, buffer = nil)
388
+ if buffer.nil?
389
+ buffer = memread(position, sizeof_type(type))
390
+ position = 0
391
+ end
392
+
393
+ # If we're asked to read a data structure, deligate to read_struct
394
+ if is_struct_type?(type)
395
+ return read_struct(type, buffer, position)
396
+ end
397
+
398
+ # If the type is an array with a given size...
399
+ # BYTE[3] for example or BYTE[ENCRYPTED_PWLEN] or even PDWORD[23]
400
+ if is_array_type?(type)
401
+ # Separate the element type from the size of the array
402
+ element_type, length = split_array_type(type)
403
+
404
+ # Have read_array take care of the rest
405
+ return read_array(element_type, length, position, buffer)
406
+ end
407
+
408
+ size = sizeof_type(type)
409
+ raw = memread(position, size, buffer)
410
+
411
+ # read/unpack data for the types we have hard-coded support for
412
+ case type
413
+ when :LPWSTR
414
+ # null-terminated string of 16-bit Unicode characters
415
+ return read_wstring(read_pointer(raw))
416
+ when :DWORD
417
+ # Both on x86 and x64, DWORD is 32 bits
418
+ return raw.unpack('V').first
419
+ when :BOOL
420
+ return raw.unpack('l').first == 1
421
+ when :LONG
422
+ return raw.unpack('l').first
423
+ end
424
+
425
+ #If nothing worked thus far, return it raw
426
+ return raw
427
+ end
428
+
429
+ # Read 'length' number of instances of 'type' from 'bufptr'
430
+ # bufptr is an index in 'buffer' or, if buffer is nil, a memory address
431
+ def read_array(type, length, bufptr, buffer = nil)
432
+ if length <= 0
433
+ return []
434
+ end
435
+
436
+ size = sizeof_type(type)
437
+ # Grab the bytes that the array consists of
438
+ buffer = memread(bufptr, size * length, buffer)
439
+
440
+ offset = 0
441
+
442
+ 1.upto(length).map do |n|
443
+ data = read_data(type, offset, buffer)
444
+
445
+ offset = offset + size
446
+
447
+ data
448
+ end
449
+ end
450
+
451
+ # construct the data structure described in 'definition' from 'buffer'
452
+ # starting from the index 'offset'
453
+ def read_struct(definition, buffer, offset = 0)
454
+ data = {}
455
+
456
+ offsets = struct_offsets(definition, offset)
457
+
458
+ definition.each do |mapping|
459
+ key, data_type = mapping
460
+
461
+ data[key] = read_data(data_type, offsets.shift, buffer)
462
+ end
463
+
464
+ data
465
+ end
466
+
467
+
468
+ # Returns true if the data type is a pointer, false otherwise
469
+ def is_pointer_type?(type)
470
+ return TYPE_DEFINITIONS[type] == :pointer
471
+ end
472
+
473
+ # Returns whether the given type represents an array of another type
474
+ # For example BYTE[3], BYTE[ENCRYPTED_PWLEN], or even PDWORD[23]
475
+ def is_array_type?(type)
476
+ return type =~ /^\w+\[\w+\]$/ ? true : false
477
+ end
478
+
479
+ # Returns true if the type passed describes a data structure, false otherwise
480
+ def is_struct_type?(type)
481
+ return type.class == Array
482
+ end
483
+
484
+
485
+ # Returns the pointer size for this architecture
486
+ def pointer_size
487
+ is_64bit ? 8 : 4
488
+ end
489
+
490
+ # Return the size, in bytes, of the given type
491
+ def sizeof_type(type)
492
+ if is_pointer_type?(type)
493
+ return pointer_size
494
+ end
495
+
496
+ if is_array_type?(type)
497
+ element_type, length = split_array_type(type)
498
+
499
+ return length * sizeof_type(element_type)
500
+ end
501
+
502
+ if is_struct_type?(type)
503
+ return sizeof_struct(type)
504
+ end
505
+
506
+ if TYPE_DEFINITIONS.has_key?(type)
507
+ primitive = TYPE_DEFINITIONS[type]
508
+
509
+ if primitive == :pointer
510
+ return pointer_size
511
+ end
512
+
513
+ if PRIMITIVE_TYPE_SIZES.has_key?(primitive)
514
+ return PRIMITIVE_TYPE_SIZES[primitive]
515
+ else
516
+ raise "Type #{type} was mapped to non-existent primitive #{primitive}"
517
+ end
518
+ end
519
+
520
+ raise "Unable to determine size for type #{type}."
521
+ end
522
+
523
+ # Calculates the size of the struct after alignment
524
+ def sizeof_struct(struct)
525
+ offsets = struct_offsets(struct, 0)
526
+ last_data_size = sizeof_type(struct.last[1])
527
+ size_no_padding = offsets.last + last_data_size
528
+
529
+ return size_no_padding + calc_padding(size_no_padding)
530
+ end
531
+
532
+ # Given a description of a data structure, returns an array containing
533
+ # the offset from the beginning for each subsequent element, taking into
534
+ # consideration alignment and padding
535
+ def struct_offsets(definition, offset)
536
+ padding = 0
537
+ offsets = []
538
+
539
+ definition.each do |mapping|
540
+ key, data_type = mapping
541
+
542
+ if sizeof_type(data_type) > padding
543
+ offset = offset + padding
544
+ end
545
+
546
+ offsets.push(offset)
547
+
548
+ offset = offset + sizeof_type(data_type)
549
+
550
+ padding = calc_padding(offset)
551
+ end
552
+
553
+ offsets
554
+ end
555
+
556
+ # http://en.wikipedia.org/wiki/Data_structure_alignment
557
+ def required_alignment
558
+ is_64bit ? 8 : 4
559
+ end
560
+
561
+ # Bytes that needed to be added to be aligned
562
+ def calc_padding(offset)
563
+ align = required_alignment
564
+
565
+ # If offset is not aligned...
566
+ if (offset % align) != 0
567
+ # Calculate padding needed to be aligned
568
+ align - (offset & (align - 1))
569
+ else
570
+ 0
571
+ end
572
+ end
573
+
574
+ # Given an explicit array definition (e.g. BYTE[23]) return size (e.g. 23) and
575
+ # and type (e.g. BYTE). If a constant is given, attempt to resolve it
576
+ # that constant
577
+ def split_array_type(type)
578
+ if type =~ /^(\w+)\[(\w+)\]$/
579
+ element_type = $1
580
+ length = $2
581
+
582
+ unless length =~ /^\d+$/
583
+ length = railgun.const(length)
584
+ end
585
+
586
+ return element_type, length
587
+ else
588
+ raise "Can not split non-array type #{type}"
589
+ end
590
+ end
591
+
592
+ # Returns true if given platform has 64bit architecture
593
+ # expects client.platform
594
+ def is_64bit_platform?(platform)
595
+ platform =~ /win64/
596
+ end
597
+
598
+ ###
599
+ # Summary:
600
+ # Evaluates a bit field, returning a hash representing the meaning
601
+ # and state of each bit.
602
+ #
603
+ # Parameters:
604
+ # value: a bit field represented by a Fixnum
605
+ # mappings: { 'WINAPI_CONSTANT_NAME' => :descriptive_symbol, ... }
606
+ #
607
+ # Returns:
608
+ # { :descriptive_symbol => true/false, ... }
609
+ ##
610
+ def judge_bit_field(value, mappings)
611
+ flags = {}
612
+ rg = railgun
613
+
614
+ mappings.each do |constant_name, key|
615
+ flags[key] = (value & rg.const(constant_name)) != 0
616
+ end
617
+
618
+ flags
619
+ end
620
+
621
+ protected
622
+
623
+ attr_accessor :railgun, :is_64bit
624
+ end # Util
625
+ end # Railgun
626
+ end # Stdapi
627
+ end # Extensions
628
+ end # Meterpreter
629
+ end # Post
630
+ end # Rex