librex 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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