浅谈gdb在漏洞发掘中的使用(合集6篇)由网友“ooooO”投稿提供,以下是小编整理过的浅谈gdb在漏洞发掘中的使用,欢迎阅读分享,希望对大家有帮助。
篇1:浅谈gdb在漏洞发掘中的使用
作者:s5Eal 来自:www.ph4nt0m.org/
浅谈gdb在漏洞发掘中的使用
[-== 翻译整理 s5Eal[at]ph4nt0m.org ==-]
[#== HP:_blank>www.ph4nt0m.org ==#]
[#===EMAIL:realbruce@163.com===#]
[data]:-01-03 ^_^
出处:2KCKI.html“ target=_blank>www.securiteam.com/securityr...5UP0B2KCKI.html
现在越来越多的人开始学习缓冲区溢出方面的原理和应用,这是一件好事,我们在使用别人写的Exploit去Hacker这儿Hacker那儿的时候,应该努力做到知其然,知其所以然,但是很多人在看了几篇即使是看上去很简单的栈溢出方面的文章后便敲起了退堂鼓,因为通篇大量gdb调试的命令和汇编代码让学习看上去变得枯燥无比,但是这方面知识的学习就是这样的。我写这篇文章的目的是总结一下在漏洞发掘中常用的一些gdb命令,降低一下新手入门时的门槛,希望能对大家有所帮助。这篇文章与一般的介绍gdb使用的文章有一定区别,因为那些文章的侧重点是使用gdb去调试一般的应用程序,而本文的则偏重于使用gdb去发掘漏洞时候常用的一些命令。鉴于本人大愚若智,本文如有疏漏之处,敬请mail to me.
运行 gdb
在 shell中,可以使用 'gdb' 命令并指定程序名作为参数来运行 gdb,例如 ‘gdb ./vuln'或者直接是‘gdb vuln’;或者在 gdb 中,可以使用 file 命令来装入要调试的程序,例如 'file vuln'。这两种方式都假设您是在包含程序的目录中执行命令。如果是为了调试core文件,则应用命令‘gdb `executable-file` `core-file`’,例如‘gdb ./vuln core’,如果系统不生成core文件,则可以使用命令‘ulimit -c 9999’打开这个功能。装入程序之后,可以用 gdb 命令 'run' 来启动程序。
绑定一个已有的进程
在shell中,一般使用ps -ax命令来查看目前系统里正在run的所有进程,最前面的一列就是对应的进程号,在gdb里我们可以这样绑定一个正在run的程序进行调试,首先利用上面的那个命令取得进程号,然后打开gdb:
[s5Eal@Heart]# gdb
GNU gdb Red Hat Linux (5.2.1-4)
Copyright Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type ”show copying“ to see the conditions.
There is absolutely no warranty for GDB. Type ”show warranty“ for details.
This GDB was configured as ”i386-redhat-linux“.
(gdb) attach 734 <-你要调试的程序的进程号
Attaching to process 734
查询内存
(gdb) x/d ‘地址’ 或者 x '地址' 显示10进制内容
(gdb) x/100s '地址' 显示由此地址开始的100个字节的十进制内容
(gdb) x 0x0804846c 显示0x0804846c处的十进制内容
(gdb) x/s '地址' 显示此地址内容对应的字符串
(gdb) x/105 0x0804846c 显示0x0804846c处开始的105个字节对应的字 符串内容
(gdb) x/x '地址' 显示16进制的地址内容
(gdb) x/10x 0x0804846c 显示0x0804846c处开始的10个字节的地址内容
(gdb) x/b 0x0804846c 显示0x0804846c处一个byte的内容
(gdb) x/10b 0x0804846c-10 显示0x0804846c-10处10个byte的内容
(gdb) x/10b 0x0804846c+20 显示0x0804846c+20处20个byte的内容
(gdb) x/20i 0x0804846c 显示0x0804846c 处开始的20个汇编指令的内容
显示可执行文件的所有分段的地址
(gdb) maintenance info sections 或者
(gdb) mai i s
例子:
[s5Eal@lHeart]# gdb vul
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type ”show copying“ to see the conditions.
There is absolutely no warranty for GDB. Type ”show warranty“ for details.
This GDB was configured as ”i386-redhat-linux“...
(gdb) maintenance info sections
Exec file:
`/root/vul', file type elf32-i386.
0x080480f4->0x08048107 at 0x000000f4: .interp ALLOC LOAD READONLY DATA HAS_C
ONTENTS
0x08048108->0x08048128 at 0x00000108: .note.ABI-tag ALLOC LOAD READONLY DATA
HAS_CONTENTS
0x08048128->0x08048158 at 0x00000128: .hash ALLOC LOAD READONLY DATA HAS_CON
TENTS
0x08048158->0x080481c8 at 0x00000158: .dynsym ALLOC LOAD READONLY DATA HAS_C
ONTENTS
0x080481c8->0x08048222 at 0x000001c8: .dynstr ALLOC LOAD READONLY DATA HAS_C
ONTENTS
0x08048222->0x08048230 at 0x00000222: .gnu.version ALLOC LOAD READONLY DATA
HAS_CONTENTS
0x08048230->0x08048250 at 0x00000230: .gnu.version_r ALLOC LOAD READONLY DAT
A HAS_CONTENTS
0x08048250->0x08048258 at 0x00000250: .rel.dyn ALLOC LOAD READONLY DATA HAS_
CONTENTS
0x08048258->0x08048278 at 0x00000258: .rel.plt ALLOC LOAD READONLY DATA HAS_
CONTENTS
0x08048278->0x08048290 at 0x00000278: .init ALLOC LOAD READONLY CODE HAS_CON
TENTS
0x08048290->0x080482e0 at 0x00000290: .plt ALLOC LOAD READONLY CODE HAS_CONT
搜寻heap,bss,got区的内容
(gdb) maintenance info sections
0x08049570->0x08049588 at 0x00000570: .bss ALLOC
0x00000000->0x00000654 at 0x00000570: .stab READONLY HAS_CONTENTS
0x00000000->0x00001318 at 0x00000bc4: .stabstr READONLY HAS_CONTENTS
0x00000000->0x000000e4 at 0x00001edc: comment READONLY HAS_CONTENTS
0x08049588->0x08049600 at 0x00001fc0: .note READONLY HAS_CONTENTS
(gdb) x/1000s 0x08049600 // 显示 heap内容
(gdb) x/1000s 0x08049570 // 显示 bss 内容
...
下断点
(gdb) disassemble main
Dump of assembler code for function main:
0x8048400
0x8048401
0x8048403
0x8048409
0x804840c
0x804840f
0x8048412
0x8048414
0x8048415
...
(gdb) break *0x8048414
Breakpoint 1 at 0x8048414
(gdb) break main
Breakpoint 2 at 0x8048409
(gdb)
删除断点
(gdb) delete breakpoints // or
(gdb) d b
Delete all breakpoints? (y or n) y
(gdb)
在stack区搜寻shellcode或者返回地址或者其他内容
(gdb) break '函数名或者地址'
(gdb) break main
Breakpoint 1 at 0x8048409
(gdb) run
Starting program: /root/vuln
Breakpoint 1, 0x8048409 in main
(gdb) x/1000s '地址' // 打印此地址开始的100个字符串
(gdb) p $esp // 查看寄存器esp的内容
$2 = (void *) 0xbffff454
(gdb) x/1000s $esp // 搜寻从esp开始向后的1000个字符串的内容
(gdb) x/1000s $esp-1000 // 搜寻从esp开始向前面的1000个字符串的内容
(gdb) x/1000s 0xbffff4b4 // 搜寻从0xbffff4b4开始向后的1000个字符串的内容
显示寄存器内容
(gdb) break main
Breakpoint 7 at 0x8048409
(gdb) r
Starting program: /home/hack/homepage/challenge/buf/basic
Breakpoint 7, 0x8048409 in main ()
(gdb) info registers
eax 0x1 1
ecx 0x8048298 134513304
edx 0x8048400 134513664
ebx 0x400f6618 1074751000
esp 0xbffff4b4 0xbffff4b4
ebp 0xbffff8bc 0xbffff8bc
esi 0x4000aa20 1073785376
edi 0xbffff924 -1073743580
eip 0x8048409 0x8048409
eflags 0x286 646
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x0 0
(gdb)
显示动态函数指针地址 (常用在return into libc exploits的构造中):
(gdb) break main
Breakpoint 1 at 0x8048409
(gdb) r
Starting program: /home/hack/homepage/challenge/buf/./basic
Breakpoint 1, 0x8048409 in main ()
(gdb) p system
$1 = {
(gdb) p strcpy
$5 = {char *(char *, char *)} 0x4006e880
显示堆栈
(gdb) backtrace
(gdb) bt
#0 0x8048476 in main ()
#1 0x40031a5e in __libc_start_main () at ../sysdeps/generic/libc-start.c:93
篇2:在Java中使用枚举Java
从C++转到Java上的 程序员 一开始总是对Java有不少抱怨,其中没有枚举就是一个比较突出的问题,那么为什么Java不支持枚举呢?从程序语言的角度讲,支持枚举意味着什么呢?我们能不能找到一种方法满足C++程序员对枚举的要求呢?那么现在就让我们一起来探讨一
从C++转到Java上的程序员一开始总是对Java有不少抱怨,其中没有枚举就是一个比较突出的问题。那么为什么Java不支持枚举呢?从程序语言的角度讲,支持枚举意味着什么呢?我们能不能找到一种方法满足C++程序员对枚举的要求呢?那么现在就让我们一起来探讨一下这个问题。
枚举类型(Enumerated Types)
让我们先看下面这一段小程序:
enum Day {SUNDAY, MONDAY, TUESDAY,
WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
这种申明提供了一种用户友好的变量定义的方法,它枚举了这种数据类型所有可能的值,即星期一到星期天。抛开具体编程语言来看,枚举所具有的核心功能应该是:
类型安全(Type Safety)
紧凑有效的枚举数值定义 (Compact, Efficient Declaration of Enumerated Values)
无缝的和程序其它部分的交互操作(Seamless integration with other language features)
运行的高效率(Runtime efficiency)
现在我们就这几个特点逐一讨论一下。
1. 类型安全
枚举的申明创建了一个新的类型。它不同于其他的已有类型,包括原始类型(整数,浮点数等等)和当前作用域(Scope)内的其它的枚举类型。当你对函数的参数进行赋值操作的时候,整数类型和枚举类型是不能互换的(除非是你进行显式的类型转换),编译器将强制这一点。比如说,用上面申明的枚举定义这样一个函数:
public void foo(Day);
如果你用整数来调用这个函数,编译器会给出错误的。
foo(4); // compilation error
如果按照这个标准,那么Pascal, Ada, 和C++是严格意义上的支持枚举,而C语言都不是。
2. 紧凑有效的枚举数值定义
定义枚巨的程序应该很简单。比如说,在Java中我们有这样一种”准枚举“的定义方法:
public static final int SUNDAY = 0;
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int THURSDAY = 4;
public static final int FRIDAY = 5;
public static final int SATURDAY = 6;
这种定义就似乎不够简洁。如果有大量的数据要定义,这一点就尤为重要,你也就会感受更深。虽然这一点不如其他另外3点重要,但我们总是希望申明能尽可能的简洁。
3. 无缝的和程序其它部分的交互操作
语言的运算符,如赋值,相等/大于/小于判断都应该支持枚举。枚举还应该支持数组下标以及switch/case语句中用来控制流程的操作。比如:
for (Day d = SUNDAY; d <= SATURDAY; ++d) {
switch(d) {
case MONDAY: ...;
break;
case TUESDAY: ...;
break;
case WEDNESDAY: ...;
break;
case THURSDAY: ...;
break;
case FRIDAY: ...;
break;
case SATURDAY:
case SUNDAY: ...;
}
}
要想让这段程序工作,那么枚举必须是整数常数,而不能是对象(objects)。Java中你可以用equals() 或是 compareTo() 函数来进行对象的比较操作,但是它们都不支持数组下标和switch语句。
4. 运行的高效率
枚举的运行效率应该和原始类型的整数一样高。在运行时不应该由于使用了枚举而导致性能比使用整数有下降。
如果一种语言满足这四点要求,那么我们可以说这种语言是真正的支持枚举。比如前面所说的Pascal, Ada, 和C++。很明显,Java不是。
Java的创始人James Gosling是个资深的C++程序员,他很清楚什么是枚举。但似乎他有意的删除了Java的枚举能力。其原因我们不得而知。可能是他想强调和鼓励使用多态性(polymorphism),不鼓励使用多重分支。而多重分支往往是和枚举联合使用的。不管他的初衷如何,我们在Java中仍然需要枚举。
Java中的几种”准枚举“类型
虽然Java 不直接支持用户定义的枚举。但是在实践中人们还是总结出一些枚举的替代品。
第一种替代品可以解释为”整数常数枚举“。如下所示:
public static final int SUNDAY = 0;
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int THURSDAY = 4;
public static final int FRIDAY = 5;
public static final int SATURDAY = 6;
这种方法可以让我们使用更有意义的变量名而不是直接赤裸裸的整数值。这样使得源程序的可读性和可维护性更好一些。这些定义可以放在任何类中。可以和其它的变量和方法混在一起。也可以单独放在一个类中。如果你选择将其单独放在一个类中,那么引用的时候要注意语法。比如”Day.MONDAY.“。如果你想在引用的时候省一点事,那么你可以将其放在一个接口中(interface),其它类只要申明实现(implement)它就可以比较方便的引用。比如直接使用MONDAY。就Java接口的使用目的而言,这种用法有些偏,不用也罢!
这种方法显然满足了条件3和4,即语言的集成和执行效率(枚举就是整数,没有效率损失)。但是他却不能满足条件1和2。它的定义有些嗦,更重要的是它不是类型安全的。这种方法虽然普遍被Java程序员采用,但它不是一种枚举的良好替代品。
第二种方法是被一些有名的专家经常提及的。我们可以称它为”对象枚举“。即为枚举创建一个类,然后用公用的该类的对象来表达每一个枚举的值。如下所示:
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.io.Serializable;
import java.io.InvalidObjectException;
public final class Day implements Comparable, Serializable {
private static int size = 0;
private static int nextOrd = 0;
private static Map nameMap = new HashMap(10);
private static Day first = null;
private static Day last = null;
private final int ord;
private final String label;
private Day prev;
private Day next;
public static final Day SUNDAY = new Day(”SUNDAY“);
public static final Day MONDAY = new Day(”MONDAY“);
public static final Day TUESDAY = new Day(”TUESDAY“);
public static final Day WEDNESDAY = new Day(”WEDNESDAY“);
public static final Day THURSDAY = new Day(”THURSDAY“);
public static final Day FRIDAY = new Day(”FRIDAY“);
public static final Day SATURDAY = new Day(”SATURDAY“);
/**
* 用所给的标签创建一个新的day.
* (Uses default value for ord.)
*/
private Day(String label) {
this(label, nextOrd);
}
/**
* Constructs a new Day with its label and ord value.
*/
private Day(String label, int ord) {
this.label = label;
this.ord = ord;
++size;
nextOrd = ord + 1;
nameMap.put(label, this);
if (first == null)
first = this;
if (last != null) {
this.prev = last;
last.next = this;
}
last = this;
}
/**
* Compares two Day objects based on their ordinal values.
* Satisfies requirements of interface java.lang.Comparable.
*/
public int compareTo(Object obj) {
return ord - ((Day)obj).ord;
}
/**
* Compares two Day objects for equality. Returns true
* only if the specified Day is equal to this one.
*/
public boolean equals(Object obj) {
return super.equals(obj);
}
/**
* Returns a hash code value for this Day.
*/
public int hashCode() {
return super.hashCode();
}
/**
* Resolves deserialized Day objects.
* @throws InvalidObjectException if deserialization fails.
*/
private Object readResolve() throws InvalidObjectException {
Day d = get(label);
if (d != null)
return d;
else {
String msg = ”invalid deserialized object: label = “;
throw new InvalidObjectException(msg + label);
}
}
/**
* Returns Day with the specified label.
* Returns null if not found.
*/
public static Day get(String label) {
return (Day) nameMap.get(label);
}
/**
* Returns the label for this Day.
*/
public String toString() {
return label;
}
/**
* Always throws CloneNotSupportedException; guarantees that
* Day objects are never cloned.
*
* @return (never returns)
*/
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/**
* Returns an iterator over all Day objects in declared order.
*/
public static Iterator iterator() {
// anonymous inner class
return new Iterator()
{
private Day current = first;
public boolean hasNext() {
return current != null;
}
public Object next() {
Day d = current;
current = current.next();
return d;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns the ordinal value of this Day.
*/
public int ord() {
return this.ord;
}
/**
* Returns the number of declared Day objects.
*/
public static int size() {
return size;
}
/**
* Returns the first declared Day.
*/
public static Day first() {
return first;
}
/**
* Returns the last declared Day.
*/
public static Day last() {
return last;
}
/**
* Returns the previous Day before this one in declared order.
* Returns null for the first declared Day.
*/
public Day prev() {
return this.prev;
}
/**
* Returns the next Day after this one in declared order.
* Returns null for the last declared Day.
*/
public Day next() {
return this.next;
}
}
枚举值被定义为公用静态对象(public static object),
此外该类含有私有构造函数;一个循环器(Iterator)用以遍历所有的值;一些Java中常用的函数,如toString(),equals()和compareTo(),以及一些方便客户程序调用的函数,如ord(),prev(),next(),first()和 last()。
这种实现方法有很好的类型安全和运行效率(条件1和4)。但是去不满足条件2和3。首先它的定义比较繁琐,大多数程序员也许因为这个而不去使用它;同时他还不可以被用作数组下标或是用在switch/case语句。这在一定程度上降低了他的使用的广泛性。
看起来,没有一种替代品是理想的。我们虽然没有权利修改Java语言,但是我们也许可以想一些办法来克服”对象枚举“的缺点,使它成为合格的枚举替代品。
一个实现枚举的微型语言(AMini-Language for Enums)
假如我发明一种枚举专用的微型语言(且叫它jEnum),它专门用来申明枚举。然后我再用一个特殊的”翻译“程序将我用这种语言定义的枚举转化为对应的”对象枚举“定义,那不是就解决了”对象枚举“定义复杂的问题了吗。当然我们很容易让这个”翻译“程序多做一些工作。比如加入Package申明,加入程序注释,说明整数值和该对象的字符串标签名称等等。让我们看下面这样一个例子:
package com.softmoore.util;
/**
* Various USA coins
*/
enum Coin { PENNY(”penny“) = 1, NICKEL(”nickel“) = 5, DIME(”dime“) = 10,
QUARTER(”quarter“) = 25, HALF_DOLLAR(”half dollar“) = 50 };
虽然”整数常数枚举“在有些情况下优点比较显著。但是总体上讲”对象枚举“提供的类型安全还是更为重要的,相比之下哪些缺点还是比较次要的。下面我们大概讲一下jEnum,使用它我们又可以得到紧凑和有效的枚举申明这一特点,也就是我们前面提到的条件2。
熟悉编译器的朋友可能更容易理解下面这一段jEnum微型语言。
compilationUnit = ( packageDecl )? ( docComment )? enumTypeDecl .
packageDecl = ”package“ packagePath ”;“ .
packagePath = packageName ( ”.“ packageName )* .
docComment = ”/**“ commentChars ”*/“ .
enumTypeDecl = ”enum“ enumTypeName ”{“ enumList ”}“ ”;“ .
enumList = enumDecl ( ”,“ enumDecl )* .
enumDecl = enumLiteral ( ”(“ stringLiteral ”)“ )? ( ”=“ intLiteral )? .
packageName = identifier .
enumTypeName = identifier .
enumLiteral = identifier .
commentChars = any-char-sequence-except-”*/“
这种语法允许在开始申明package,看起来和Java语言还挺像。你可以增加一些javadoc的注解,当然这不是必须的。枚举类型的申明以关键字”enum“开头,枚举的值放在花括号中{},多个值之间用逗号分开。每一个值的申明包括一个标准的Java变量名,一个可选的字符串标签,可选的等号(=)和一个整数值。
如果你省略了字符串标签,那么枚举的变量名就会被使用;如果你省略了等号和后面的整数值,那么它将会自动按顺序给你的枚举赋值,如果没有使用任何数值,那么它从零开始逐步增加(步长为1)。字符串标签作为toString()方法返回值的一部分,而整数值则作为ord()方法的返回值。如下面这段申明:
enum Color { RED(”Red“) = 2, WHITE(”White“) = 4, BLUE };
RED 的标签是 ”Red“,值为 2 ;
WHITE的标签是”White“,值为4;
BLUE的标签是”BLUE“ ,值为5 。
要注意的是在Java中的保留字在jEnum也是保留的。比如你不可以使用this作为package名,不可以用for为枚举的变量名等等。枚举的变量名和字符串标签必须是不同的,其整数值也必须是严格向上增加的,象下面这段申明就是不对的,因为它的字符串标签不是唯一的。
enum Color { RED(”Red“), WHITE(”BLUE“), BLUE };
下面这段申明也是不对的,因为WHITE会被自动赋值2 ,和BLUE有冲突。
enum Color { RED = 1, WHITE, BLUE = 2 };
下面这是一个具体的实例。它将会被”翻译“程序使用,用以转换成我们枚举申明为可编译的Java源程序。
package com.softmoore.jEnum;
/**
* This class encapsulates the symbols (a.k.a. token types)
* of a language token.
*/
enum Symbol {
identifier,
enumRW(”Reserved Word: enum“),
abstractRW(”Reserved Word: abstract“),
assertRW(”Reserved Word: assert“),
booleanRW(”Reserved Word: boolean“),
breakRW(”Reserved Word: break“),
byteRW(”Reserved Word: byte“),
caseRW(”Reserved Word: case“),
catchRW(”Reserved Word: catch“),
charRW(”Reserved Word: char“),
classRW(”Reserved Word: class“),
constRW(”Reserved Word: const“),
continueRW(”Reserved Word: continue“),
defaultRW(”Reserved Word: default“),
doRW(”Reserved Word: do“),
doubleRW(”Reserved Word: double“),
elseRW(”Reserved Word: else“),
extendsRW(”Reserved Word: extends“),
finalRW(”Reserved Word: final“),
finallyRW(”Reserved Word: finally“),
floatRW(”Reserved Word: float“),
forRW(”Reserved Word: for“),
gotoRW(”Reserved Word: goto“),
ifRW(”Reserved Word: if“),
implementsRW(”Reserved Word: implements“),
importRW(”Reserved Word: import“),
instanceOfRW(”Reserved Word: instanceOf“),
intRW(”Reserved Word: int“),
interfaceRW(”Reserved Word: interface“),
longRW(”Reserved Word: long“),
nativeRW(”Reserved Word: native“),
newRW(”Reserved Word: new“),
nullRW(”Reserved Word: null“),
packageRW(”Reserved Word: package“),
privateRW(”Reserved Word: private“),
protectedRW(”Reserved Word: protected“),
publicRW(”Reserved Word: public“),
returnRW(”Reserved Word: return“),
shortRW(”Reserved Word: short“),
staticRW(”Reserved Word: static“),
strictfpRW(”Reserved Word: strictfp“),
superRW(”Reserved Word: super“),
switchRW(”Reserved Word: switch“),
synchronizedRW(”Reserved Word: synchronized“),
thisRW(”Reserved Word: this“),
throwRW(”Reserved Word: throw“),
throwsRW(”Reserved Word: throws“),
transientRW(”Reserved Word: transient“),
tryRW(”Reserved Word: try“),
voidRW(”Reserved Word: void“),
volatileRW(”Reserved Word: volatile“),
whileRW(”Reserved Word: while“),
equals(”=“),
leftParen(”(“),
rightParen(”)“),
leftBrace(”“),
comma(”,“),
semicolon(”;“),
period(”.“),
intLiteral,
stringLiteral,
docComment,
EOF,
unknown
};
如果对Day的枚举申明存放在Day.enum文件中,那么我们可以将这个文件翻译成Java源程序。
$ java -jar jEnum.jar Day.enum
翻译的结果就是Day.javaJava源程序,内容和我们前面讲的一样,还包括程序注释等内容。如果想省一点事,你可以将上面比较长的命令写成一个批处理文件或是Unix,Linux上的shell script,那么以后使用的时候就可以简单一些,比如:
$ jec Day.enum
关于jEnum有四点注意事项要说明一下。
1. 申明文件名不一定后缀为”.enum.“,其它合法文件后缀都可以。
2. 如果文件后缀不是”.enum.“,那么翻译程序将首先按给出的文件名去搜索,如果没有,就假定给出的文件名是省略了”.enum.“后缀的。像这种命令是可以的:
$ java -jar jEnum.jar Day
3. 生成的Java源程序文件名是按照申明文件内的定义得出的,而不是依据申明文件的名称。
4. 翻译程序还接受以下几个开关
-o 生成”对象枚举“类枚举,是缺省值
-c 生成”整数常数枚举“类枚举,用类来实现
-i 生成”整数常数枚举“类枚举,用接口来实现
要注意的是,-C开关虽然生成”整数常数枚举“,但它同时还提供了一些”对象枚举“中所具有的方法,如first(), last(),toString(int n),prev(int n), 和next(int n)。
jEnum工具可以从网上自由下载,其地址是:www.onjava.com/onjava//04/23/examples/jEnum.zip
原文转自:www.ltesting.net
篇3:在Word中使用创建文档
除了通用型的空白文档Word2010/'>模板之外,Word2010中还内置了多种文档模板,如博客文章模板、书法字帖模板等等,另外,Office.com网站还提供了证书、奖状、名片、简历等特定功能模板。借助这些模板,用户可以创建比较专业的Word2010文档。在Word2010中使用模板创建文档的步骤如下所述:
第1步,打开Word2010文档窗口,依次单击“文件”→“新建”按钮。第2步,在打开的“新建”面板中,用户可以单击“博客文章”、“书法字帖”等Word2010自带的模板创建文档,还可以单击Office.com提供的“名片”、“日历”等在线模板。例如单击“样本模板”选项,如图120501所示,
图2009120501 单击“样本模板”选项第3步,打开样本模板列表页,单击合适的模板后,在“新建”面板右侧选中“文档”或“模板”单选框(本例选中“文档”选项),然后单击“创建”按钮,如图2009120502所示。
图2009120502 单击“创建”按钮第4步,打开使用选中的模板创建的文档,用户可以在该文档中进行编辑,如图2009120503所示。
图2009120503 使用模板创建的文档小提示:除了使用Word2010已安装的模板,用户还可以使用自己创建的模板和Office.com提供的模板。在下载Office.com提供的模板时,Word2010会进行正版验证,非正版的Word2010版本无法下载Office Online提供的模板。
篇4:在VisualStudio中使用GIT
GIT作为源码管理的方式现在是越来越流行了,在VisualStudio 中,就通过插件的现实对GIT进行了官方支持,并且这个插件在VS中已经转正,本文在这里简单的介绍一下如何在Visual Studio中使用GIT进行源码管理。
PS: 由于篇幅所限,本文并没有对相关基础知识进行介绍,在读取本文前,假定你已经对GIT有一定的了解,并且对VisualStudio的团队管理器比较熟悉,后续有时间的话再进行相关知识的介绍。
将项目添加到GIT源码管理
将项目添加到GIT源码管理和通过TFS管理方式一样,直接在解决方案的右键菜单中点取即可。
和之前不同的是,此时会出现一个对话框会让你选择使用传统的TFS方式还是GIT方式来管理,这里选择Git。
选择完后,我们就可以在团队资源管理器中看到项目已经被托管起来,并且已经新建你一个master的分支。
安装第三方Git工具
从上面的截图我们也可以看到,团队管理器视图会提示你安装第三方Git工具。虽然不安装也可以使用,但是VisualStudio中集成的功能是比较少的(就目前来看,是不够用的),如果要使用其它的功能,则需要通过第三方Git工具来实现。
安 装方式比较简单,直接按照提示不停的下一步即可,这里就不多介绍了。系统自己带的是Git For Windows,带一个命令行和一个GUI程序,命令行可以在VS中直接启动,比较方便。你也可以自己安装其它的工具,第三方工具和系统自带的Git不冲 突,可以同时使用。
提交更改
从团队管理器中我们可以看到,对于Git的操作分包括更改、分支、提交三种。当我们把项目加入源码管理后,首先就是需要提交我们的修改,这里使用的是”更改“功能,而不是”提交“(”提交“页面是进行发布到Git服务器管理的)。进入提交页面后,操作界面如下:
首次使用时需要配置用户名和密码,这个是全局设置,
然后输入提交消息,点击提交按钮即可提交了。提交完成后,额可以到分支页面查看所有提交的历史记录。
创建分支
创建分支比较简单,直接点击新分支链接,选择源分支,输入名称即可:
切换分支
创建分支后,系统便自动切换到新分支上 ,此时我们的修改都是在新分支上进行。
如果要切换分支,直接在分支页面双击相应的分支即可,选中的分支高亮显示,同时代码也会自动切换到相应的分支,非常方便。
合并分支
分支修改完成后,往往会将其合并到主线上,点击合并链接,选择相应的分支,点击合并按钮即可。
发布到Git服务器
本地修改完成后,需要将其发布到Git服务器,以供备份和项目其它成员分享。发布的方法也比较简单:
进入”提交“页面
选择要发布的分支
输入Git仓库的URL
点击发布按钮
首次发布时会出现一个对话框提示输入Git仓库的身份认证信息。
和Git服务器同步修改
和Git服务器同步修改的常用命令后fetch、push、pull,在VisualStudio中也有对其进行支持,这里就不多介绍了。
如果你嫌麻烦的话,甚至可以直接点击同步按钮,一次性完成所有操作。
克隆Git仓库
对于非项目创建者的团队成员来说,首先的一步就是克隆Git仓库。操作方式如下:首先在团队管理器窗口中选择”连接到团队项目“,选择” 克隆“链接,输入远程Git库的URL和本地路径,点击克隆按钮即可。
来自:www.cnblogs.com/TianFang/p/3345038.html
篇5:考研政治训练营 在复习中发掘潜力
考研政治训练营 在复习中发掘潜力
那么如何才能在考研政治中取得成功呢?面对繁多的需要记诵的内容,是自暴自弃、是随波逐流,还是坐起身来赶紧复习呢?复习考研政治是要讲究方法的。作为并不是很熟悉政治的考生来讲该怎么复习政治呢?
注意复习的方法和技巧。复习课本不是逐字逐句地细致阅读,但也不是简单的翻一遍,或是单纯的背诵一遍,必须要注意方法和技巧。虽说是基础阶段的第一轮复习,但实际上它包含两遍:
(1)先把课本读“厚”。具体做法是:结合《大纲》,把每一课的知识点都找出来,逐个消化。需要知识的识记,需要理解运用的知识点,要再通读一下课本上的相关内容,特别是自己不理解的重点问题,除了求助同学之外,还要做少量相关的习题。这一遍复习不能留下任何的`知识死角。要下苦功夫细致地复习,时间不够要抽时间,把识记、看课本和做题有效地结合起来。另外,每复习一个阶段要做一套检测题,检查一下自己知识点上还有没有漏洞,以便及时查漏补缺。李老师建议:复习完每一章内容后做一套试题,自我检测。
(2)再把课本读“薄”。根据记忆规律,我们过一段时间还要重复复习一下前面我们复习过的内容,但时间有限,我们必须找出可行的方法!专家建议是:每进行完一个阶段,就要及时地总结一下,用一个专门的本子,列出知识框架结构,并找出里面重点的知识和自己认为比较难的知识点,以备日后快速有效的复习。同时要做一个习题集,记录下那些自己做错的且比较重要的试题,每次考试前都要抽时间翻一下。
掌握科学、高效的应试技巧与方法。科学的应试技巧和方法主要包括:头脑清醒、情绪稳定;仔细审题、务求准确;先易后难,掌握时间;思路清晰,逻辑严密;语言流畅,表达规范;沉着冷静,随机应变;巧妙组合,自主发挥;注意复查,切勿急躁。
考生在解答分析题时尤其需要注意以下几点:首先,要仔细审题,认真阅读材料,分清每个材料所蕴含的主要观点,然后选择与题目要求相符合的基本原理。由于有的题目对答题的内容、范围、要求等没有明确规定,考生难以直接从材料对比分析中概括出来某一基本原理。因此,这就需要考生在复习备考时加强对基本理论和基本知识的理解、掌握,努力提高自己的辨别能力和概括能力。
其次,要全面、完整地阐述有关基本原理。要牢记,运用基本理论分析实际问题主要是进行理论性的回答,并不要求就具体实际问题作繁琐的分析。还要提醒考生注意的是,有时所给的事实材料或命题判断可能体现了若干个基本原理,而不只是单一的原理,这就需要考生全面考虑,抓住最恰当的原理来论述。
最后,要紧扣题目材料,准确引用材料中的文字和引证其中的有关事实,运用有关理论作出恰当的综合、概括、比较、鉴别和分析。提醒同学们在此复习阶段一定要把错题本重视起来,对于自己之前错的题型认真归纳总结一下。
关注和剖析社会现实问题和理论“热点”问题。研究生入学考试政治理论方面的试题,固然把政治理论课中的基本原理作为重要的评价目标,但是根本的评价目标是:在考查基本知识、基本理论的基础上,注重考查考生运用马克思主义的基本立场、观点和方法分析和解决实际问题的能力。在对这一“能力”的考查方面,“评价目标”中提出了两个具体要求:“运用有关原理,解释和论证某种观点,辨明理论是非”;“用马克思主义的观点和方法,比较和分析有关社会现象或实际问题”。要适应上述考查目标的要求,考生首先必须通过多种途径,关注和熟悉国内外的重大事件、重要的社会现实问题以及当前的理论“热点”、某些理论是非问题;然后尝试运用学过的马克思主义原理去分析、解剖,或采取在同学中进行讨论的方式,提高运用基本原理去理解、认识社会实际问题的能力和辨别理论是非的能力。
考研路途漫漫,希望以上建议能给后来考研的同学们一点帮助。扎扎实实,平常对待,坚持不懈,定会胜利!考研教育网预祝学子在考研中取得佳绩!
大学网考研频道。篇6:php://filter在php漏洞中的利用
1、php://filter基础
php.net中的描述,php.net/manual/zh/wrappers.php.php,php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用。这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。更详细的内容可以查看上面的链接。
php.net中两个基本的例子:
/* 这会以大写字母输出 www.myhack58.com 的全部内容 */
readfile(”php://filter/read=string.toupper/resource=www.myhack58.com“);
/* 这会通过 rot13 过滤器筛选出字符 ”Hello World“
然后写入当前目录下的 example.txt */
file_put_contents(”php://filter/write=string.rot13/resource=example.txt“,”Hello World");
在这个例子中,php会先把Hello World字符串做string.rot13转换然后再写入文件,这在场景A中会有用到。
2、利用场景
A.在黑哥(膜拜黑哥)的关于[技术挑战-2]有提到,这里只说和php://filter有关的部分。
下面一段代码:
$str = '
$fname = $_GET['f'];
file_put_contents($fname,$str);
如何成功将phpinfo();写入文件并执行?利用上面提到的基础知识可以提交如下链接:
127.0.0.1:81/test.php?f=php%3A%2f%2ffilter%2fwrite%3Dconvert.base64-decode%2fresource%3Dwebshell.php&c=dddPD9waHBpbmZvKCk7Pz4
值得注意的有两点:
1). base64_decode()会忽略要解码字符串中无效字符像?;等,这里给出base64_decode()函数忽略无效字符相应的c函数代码
170 ch = base64_reverse_table[ch];
171 if ((!strict && ch < 0) || ch == -1) { /* a space or some other separator character, we simply skipo ver */ www.myhack58.com
172 continue;
173 } else if (ch == -2) {
174 efree(result);
175 return NULL;
176 }
177
2). 将
原因的话可以查看base64编码的原理。
B.本地文件包含
如果有这么一段代码:
include($_GET[‘file’]);
你想查看和本代码同一目录下config.php的内容。如何查看呢?
127.0.0.1:81/test.php?file=php://filter/convert.base64-encode/resource=config.php
3、参考:
www.*****.com/en/advisories/advisory-032009-piwik-cookie-unserialize-vulnerability/
php.net/manual/zh/wrappers.php.php
★ 个人简历范文软件
【浅谈gdb在漏洞发掘中的使用(合集6篇)】相关文章:
个人嵌入式学习总结2024-04-30
木马作文600字2022-10-11
木马的童话2022-04-30
嵌入式实习总结2023-02-11
工程项目升级计划书2022-05-24
研发部年度计划2023-07-02
研发部设计个人简历2022-05-04
家具业务员总结与计划2023-10-12
金融项目经验范文2022-05-20
个人简历怎么写?简历中项目经验写法2022-12-09