DO NOT READ THIS ARTICLE. I wrote bullshit in English.

This lab I have finished once, so this article is just for fun.

Phase-1

  1. 0000000000400ee0 <phase_1>:
  2. 400ee0: 48 83 ec 08 sub $0x8,%rsp
  3. 400ee4: be 00 24 40 00 mov $0x402400,%esi
  4. 400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
  5. 400eee: 85 c0 test %eax,%eax
  6. 400ef0: 74 05 je 400ef7 <phase_1+0x17>
  7. 400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
  8. 400ef7: 48 83 c4 08 add $0x8,%rsp
  9. 400efb: c3 retq

Just scan the memory of address [0x402400] . GDB command is x /s 0x402400 .

  1. (gdb) x /s 0x402400
  2. 0x402400: "Border relations with Canada have never been better."

We can see that the answer is Border relations with Canada have never been better. .

Phase-2

  1. 0000000000400efc <phase_2>:
  2. 400efc: 55 push %rbp
  3. 400efd: 53 push %rbx
  4. 400efe: 48 83 ec 28 sub $0x28,%rsp
  5. 400f02: 48 89 e6 mov %rsp,%rsi
  6. 400f05: e8 52 05 00 00 callq 40145c <read_six_numbers>
  7. 400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)
  8. 400f0e: 74 20 je 400f30 <phase_2+0x34>
  9. 400f10: e8 25 05 00 00 callq 40143a <explode_bomb>
  10. 400f15: eb 19 jmp 400f30 <phase_2+0x34>
  11. 400f17: 8b 43 fc mov -0x4(%rbx),%eax
  12. 400f1a: 01 c0 add %eax,%eax
  13. 400f1c: 39 03 cmp %eax,(%rbx)
  14. 400f1e: 74 05 je 400f25 <phase_2+0x29>
  15. 400f20: e8 15 05 00 00 callq 40143a <explode_bomb>
  16. 400f25: 48 83 c3 04 add $0x4,%rbx
  17. 400f29: 48 39 eb cmp %rbp,%rbx
  18. 400f2c: 75 e9 jne 400f17 <phase_2+0x1b>
  19. 400f2e: eb 0c jmp 400f3c <phase_2+0x40>
  20. 400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx
  21. 400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp
  22. 400f3a: eb db jmp 400f17 <phase_2+0x1b>
  23. 400f3c: 48 83 c4 28 add $0x28,%rsp
  24. 400f40: 5b pop %rbx
  25. 400f41: 5d pop %rbp
  26. 400f42: c3 retq

From this code read_six_number , we can see that we should input six numbers. And the we can know that there is a loop, and the most important line of code is :

  1. 400f1a: 01 c0 add %eax,%eax

Now, we can guess that it should be a geometric series, whose ratio is 2. What is the first element of the number series? We can see:

  1. 400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)
  2. 400f0e: 74 20 je 400f30 <phase_2+0x34>
  3. 400f10: e8 25 05 00 00 callq 40143a <explode_bomb>

OK, we can see that if (%rsp) is not equal to 0x1 , it will call function explode_bomb .

Thus, the answer is : 1 2 4 8 16 32 .

Phase-3

  1. 0000000000400f43 <phase_3>:
  2. 400f43: 48 83 ec 18 sub $0x18,%rsp
  3. 400f47: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
  4. 400f4c: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
  5. 400f51: be cf 25 40 00 mov $0x4025cf,%esi
  6. 400f56: b8 00 00 00 00 mov $0x0,%eax
  7. 400f5b: e8 90 fc ff ff callq 400bf0 <__isoc99_sscanf@plt>
  8. 400f60: 83 f8 01 cmp $0x1,%eax
  9. 400f63: 7f 05 jg 400f6a <phase_3+0x27>
  10. 400f65: e8 d0 04 00 00 callq 40143a <explode_bomb>
  11. 400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp)
  12. 400f6f: 77 3c ja 400fad <phase_3+0x6a>
  13. 400f71: 8b 44 24 08 mov 0x8(%rsp),%eax
  14. 400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)
  15. 400f7c: b8 cf 00 00 00 mov $0xcf,%eax
  16. 400f81: eb 3b jmp 400fbe <phase_3+0x7b>
  17. 400f83: b8 c3 02 00 00 mov $0x2c3,%eax
  18. 400f88: eb 34 jmp 400fbe <phase_3+0x7b>
  19. 400f8a: b8 00 01 00 00 mov $0x100,%eax
  20. 400f8f: eb 2d jmp 400fbe <phase_3+0x7b>
  21. 400f91: b8 85 01 00 00 mov $0x185,%eax
  22. 400f96: eb 26 jmp 400fbe <phase_3+0x7b>
  23. 400f98: b8 ce 00 00 00 mov $0xce,%eax
  24. 400f9d: eb 1f jmp 400fbe <phase_3+0x7b>
  25. 400f9f: b8 aa 02 00 00 mov $0x2aa,%eax
  26. 400fa4: eb 18 jmp 400fbe <phase_3+0x7b>
  27. 400fa6: b8 47 01 00 00 mov $0x147,%eax
  28. 400fab: eb 11 jmp 400fbe <phase_3+0x7b>
  29. 400fad: e8 88 04 00 00 callq 40143a <explode_bomb>
  30. 400fb2: b8 00 00 00 00 mov $0x0,%eax
  31. 400fb7: eb 05 jmp 400fbe <phase_3+0x7b>
  32. 400fb9: b8 37 01 00 00 mov $0x137,%eax
  33. 400fbe: 3b 44 24 0c cmp 0xc(%rsp),%eax
  34. 400fc2: 74 05 je 400fc9 <phase_3+0x86>
  35. 400fc4: e8 71 04 00 00 callq 40143a <explode_bomb>
  36. 400fc9: 48 83 c4 18 add $0x18,%rsp
  37. 400fcd: c3 retq

Look at this line of code:

  1. 400f51: be cf 25 40 00 mov $0x4025cf,%esi

Run x /s 0x4025cf in GDB, it will print: "%d %d" . Thus, we should input 2 int in this phase.

And we can see that there are many annoying jmp 0x400fb9 instructions in this assembly code, so we can infer that there is a switch-case structure.

The first 2 lines of code below shows that the first number we input (stored in [%rsp + 8]) is less equal than 7, otherwise it will call explode_bomb . The last 2 lines tell us that the program will jump to an address according to our first number.

  1. 400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp)
  2. 400f6f: 77 3c ja 400fad <phase_3+0x6a>
  3. 400f71: 8b 44 24 08 mov 0x8(%rsp),%eax
  4. 400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)

We know that the first number (now it has been copied to %rax) can be one of number in [0,1,2,3,4,5,6,7]. So scan the address [0x402470 + %rax * 8] :

  1. (gdb) x /x 0x402470 + 8 * 0 => 0x402470: 0x00400f7c => 0 0xcf
  2. (gdb) x /x 0x402470 + 8 * 1 => 0x402478: 0x00400fb9 => 1 0x137
  3. (gdb) x /x 0x402470 + 8 * 2 => 0x402480: 0x00400f83 => 2 0x2c3
  4. (gdb) x /x 0x402470 + 8 * 3 => 0x402488: 0x00400f8a => 3 0x100
  5. (gdb) x /x 0x402470 + 8 * 4 => 0x402490: 0x00400f91 => 4 0x185
  6. (gdb) x /x 0x402470 + 8 * 5 => 0x402498: 0x00400f98 => 5 0xce
  7. (gdb) x /x 0x402470 + 8 * 6 => 0x4024a0: 0x00400f9f => 6 0x2aa
  8. (gdb) x /x 0x402470 + 8 * 7 => 0x4024a8: 0x00400fa6 => 7 0x147

When the first number we input is 0, the program will jump to 0x400f7c. And the code at 0x400f7c is :

  1. 400f7c: b8 cf 00 00 00 mov $0xcf,%eax

So the second number is 0xcf = 207. Total answer is 0 207.

Phase-4

  1. ; first call is func4(edx=a, esi=b, edi=x)
  2. 0000000000400fce <func4>:
  3. 400fce: 48 83 ec 08 sub $0x8,%rsp
  4. 400fd2: 89 d0 mov %edx,%eax ; eax = a
  5. 400fd4: 29 f0 sub %esi,%eax ; eax = eax - esi = a - b = t1
  6. 400fd6: 89 c1 mov %eax,%ecx ; ecx = eax = a - b
  7. 400fd8: c1 e9 1f shr $0x1f,%ecx ; ecx = ecx >> 31 = t1 >> 31 = t2
  8. 400fdb: 01 c8 add %ecx,%eax ; eax = eax + ecx = t1 + t2
  9. 400fdd: d1 f8 sar %eax ; eax = eax >> 1 = (t1+t2)>>1, t1=(t1+t2)>>1
  10. 400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx ; ecx = eax + esi = t1 + b, t2=t1+b
  11. 400fe2: 39 f9 cmp %edi,%ecx ; ecx <= x ? () : (2 * func4())
  12. 400fe4: 7e 0c jle 400ff2 <func4+0x24> ;
  13. 400fe6: 8d 51 ff lea -0x1(%rcx),%edx ; edx = ecx - 1 = t2 - 1
  14. 400fe9: e8 e0 ff ff ff callq 400fce <func4> ; func4(edx=t2-1, b, x)
  15. 400fee: 01 c0 add %eax,%eax ; return 2 * func4()
  16. 400ff0: eb 15 jmp 401007 <func4+0x39>
  17. 400ff2: b8 00 00 00 00 mov $0x0,%eax ; eax = 0
  18. 400ff7: 39 f9 cmp %edi,%ecx ; ecx >= edi ? (return 0) : ()
  19. 400ff9: 7d 0c jge 401007 <func4+0x39>
  20. 400ffb: 8d 71 01 lea 0x1(%rcx),%esi ; esi = ecx + 1
  21. 400ffe: e8 cb ff ff ff callq 400fce <func4> ; func4()
  22. 401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax ; return 2 * func4() + 1
  23. 401007: 48 83 c4 08 add $0x8,%rsp
  24. 40100b: c3 retq
  25. 000000000040100c <phase_4>:
  26. 40100c: 48 83 ec 18 sub $0x18,%rsp
  27. 401010: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
  28. 401015: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
  29. 40101a: be cf 25 40 00 mov $0x4025cf,%esi
  30. ; scan the address 0x4025cf
  31. 40101f: b8 00 00 00 00 mov $0x0,%eax
  32. 401024: e8 c7 fb ff ff callq 400bf0 <__isoc99_sscanf@plt>
  33. 401029: 83 f8 02 cmp $0x2,%eax
  34. 40102c: 75 07 jne 401035 <phase_4+0x29>
  35. 40102e: 83 7c 24 08 0e cmpl $0xe,0x8(%rsp)
  36. ; the 1st number x should be x <= 15, otherwise explode
  37. 401033: 76 05 jbe 40103a <phase_4+0x2e>
  38. 401035: e8 00 04 00 00 callq 40143a <explode_bomb>
  39. 40103a: ba 0e 00 00 00 mov $0xe,%edx
  40. 40103f: be 00 00 00 00 mov $0x0,%esi
  41. 401044: 8b 7c 24 08 mov 0x8(%rsp),%edi
  42. 401048: e8 81 ff ff ff callq 400fce <func4>
  43. ; func4(edx=0xe, esi=0x0, edi=x)
  44. 40104d: 85 c0 test %eax,%eax
  45. ; the returned val of func4 shouble 0
  46. 40104f: 75 07 jne 401058 <phase_4+0x4c>
  47. 401051: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)
  48. ; the 2nd number y should be 0, otherwise explode
  49. ; so the total condition is func(0xe,0x0,x) == 0 and y = 0
  50. 401056: 74 05 je 40105d <phase_4+0x51>
  51. 401058: e8 dd 03 00 00 callq 40143a <explode_bomb>
  52. 40105d: 48 83 c4 18 add $0x18,%rsp
  53. 401061: c3 retq

phase_4 call a function func4, which is a recursion. Scan the address 0x4025cf, GDB will print "%d %d", which means we should input 2 int numbers. Assume that our input is x y. The x will be stored in %rsp + 0x8 and y in %rsp + 0xc. Then phase_4 would call func4(edx=0xe, esi=0x0, edi=x), and this function call passes parameters by register. Read the comment above.

The conditions for passing phase_4 is input x y to let func(0xe, 0x0, x) return 0 and x should be less equal than 15 and y must be 0.

Read the code of func4, we can change it into C code:

  1. int func4(int a, int b, int x)
  2. {
  3. x; // edi
  4. int t1 = a - b; // eax
  5. int t2 = ((unsigned int)t1) >> 31; // ecx
  6. t1 = (t1 + t2) >> 1;
  7. t2 = t1 + b;
  8. if (t2 <= x)
  9. {
  10. t1 = 0;
  11. if (t2 < x)
  12. return 2 * func4(a, t2 + 1, x) + 1;
  13. return t1;
  14. }
  15. else
  16. return 2 * func4(t2 - 1, b, x);
  17. }

What we need to pay attention to is this instruction: 400fd8: shr $0x1f,%ecx. The shr implies that it will operation on a unsigned type (read the C code above) .

Therefore, we can find x by enumeration.

  1. int main()
  2. {
  3. int x = 0;
  4. for (x = 0; x <= 15; x++)
  5. {
  6. int t = func4(0xe, 0x0, x);
  7. if (t == 0)
  8. printf("%d ", x);
  9. }
  10. }

The result is:

  1. (x,y) = (0,0), (1,0), (3,0), (7,0)

Phase-5

  1. 0000000000401062 <phase_5>:
  2. 401062: 53 push %rbx
  3. 401063: 48 83 ec 20 sub $0x20,%rsp
  4. ; 32 bytes stack for temporary variable
  5. 401067: 48 89 fb mov %rdi,%rbx
  6. ; rdi is the address of strings we input
  7. 40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
  8. 401071: 00 00
  9. ; I don't understand here
  10. 401073: 48 89 44 24 18 mov %rax,0x18(%rsp)
  11. 401078: 31 c0 xor %eax,%eax
  12. 40107a: e8 9c 02 00 00 callq 40131b <string_length>
  13. 40107f: 83 f8 06 cmp $0x6,%eax
  14. ; we should input a string, whose len is 6
  15. ; do while loop begin, eax=0 is the counter
  16. 401082: 74 4e je 4010d2 <phase_5+0x70>
  17. 401084: e8 b1 03 00 00 callq 40143a <explode_bomb>
  18. 401089: eb 47 jmp 4010d2 <phase_5+0x70>
  19. 40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx
  20. ; t = str[i]
  21. 40108f: 88 0c 24 mov %cl,(%rsp)
  22. 401092: 48 8b 14 24 mov (%rsp),%rdx
  23. 401096: 83 e2 0f and $0xf,%edx
  24. ; t = str[i] & 0xf
  25. 401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
  26. 4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)
  27. ; array[rsp+0x10+rax] = str2[t]
  28. 4010a4: 48 83 c0 01 add $0x1,%rax
  29. 4010a8: 48 83 f8 06 cmp $0x6,%rax
  30. ; eax++ until out of str.length
  31. 4010ac: 75 dd jne 40108b <phase_5+0x29>
  32. 4010ae: c6 44 24 16 00 movb $0x0,0x16(%rsp)
  33. 4010b3: be 5e 24 40 00 mov $0x40245e,%esi
  34. ; "flyers"
  35. 4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
  36. 4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal>
  37. 4010c2: 85 c0 test %eax,%eax
  38. 4010c4: 74 13 je 4010d9 <phase_5+0x77>
  39. 4010c6: e8 6f 03 00 00 callq 40143a <explode_bomb>
  40. 4010cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
  41. 4010d0: eb 07 jmp 4010d9 <phase_5+0x77>
  42. 4010d2: b8 00 00 00 00 mov $0x0,%eax
  43. 4010d7: eb b2 jmp 40108b <phase_5+0x29>
  44. 4010d9: 48 8b 44 24 18 mov 0x18(%rsp),%rax
  45. 4010de: 64 48 33 04 25 28 00 xor %fs:0x28,%rax
  46. 4010e5: 00 00
  47. 4010e7: 74 05 je 4010ee <phase_5+0x8c>
  48. 4010e9: e8 42 fa ff ff callq 400b30 <__stack_chk_fail@plt>
  49. 4010ee: 48 83 c4 20 add $0x20,%rsp
  50. 4010f2: 5b pop %rbx
  51. 4010f3: c3 retq

This phase_5 want us to input a string str (its length is 6), which is a simple phase.

There is a hash table in the program:

  1. hex index: 0 1 2 3 4 5 6 7 8 9 A B C D E F
  2. hash str : m a d u i e r s n f o t v b y l

phase_5 construct a hash function is: f(x) = hash_str[x & 0xf].

We aim to let f(str) = "flyers".

flyers is equal to character 9, F, E, 4, 5, 6 in the hash table, thus, str[i] & 0xf (i=0,...,5) should be 9, F, E, 4, 5, 6. We can check the ASCII table to get characters:

  1. 0x39 0x3F 0x3E 0x34 0x35 0x36
  2. '9' '?' '>' '4' '5' '6'

The string "9?>456" is the key to pass this phase.

If you still do not understand, see the C code:

  1. void phase5(const char *input)
  2. {
  3. const char *hash_str = "maduiersnfotvbyl";
  4. char array[7];
  5. int i = 0;
  6. for (i = 0; i < 6; i++)
  7. array[i] = hash_str[input[i] & 0xf];
  8. if (sting_not_equal(array, "flyers"))
  9. explode();
  10. }

Evaluation

All the answers in a text files sin.ans:

  1. unix > cat sin.ans
  2. Border relations with Canada have never been better.
  3. 1 2 4 8 16 32
  4. 0 207
  5. 7 0 DrEvil
  6. 9?>456
  7. 4 3 2 1 6 5
  8. 20

Execute the bomb binary file:

  1. unix > ./bomb sin.ans
  2. Welcome to my fiendish little bomb. You have 6 phases with
  3. which to blow yourself up. Have a nice day!
  4. Phase 1 defused. How about the next one?
  5. That's number 2. Keep going!
  6. Halfway there!
  7. So you got that one. Try this one.
  8. Good work! On to the next...
  9. Curses, you've found the secret phase!
  10. But finding it and solving it are quite different...
  11. Wow! You've defused the secret stage!
  12. Congratulations! You've defused the bomb!

Summary

好无聊,希望早点开学

CSAPP-bomblab的更多相关文章

  1. CSAPP 之 BombLab 详解

    前言 本篇博客将会展示 CSAPP 之 BombLab 的拆弹过程,粉碎 Dr.Evil 的邪恶阴谋.Dr.Evil 的替身,杀手皇后,总共设置了 6 个炸弹,每个炸弹对应一串字符串,如果字符串错误, ...

  2. CSAPP:bomblab

    BOMBLAB实验总结 CSAPP实验BOMB,很头疼,看不懂,勉强做完了. 答案是这样的: Border relations with Canada have never been better. ...

  3. 终于要开始做大名鼎鼎的BombLab了!

    首先是一些准备工作 lab下载地址:http://csapp.cs.cmu.edu/3e/labs.html 第二个的Bomblab的 self-study handout就是 在做这个lab前,首先 ...

  4. 在Ubuntu下使用 csapp.h 和 csapp.c

    它山之石可以攻玉. 对于<深入理解计算机系统>这本神人写就的神书, 我等凡人就不评论什么啦. 这本书的 第二,三 部分, 真的真的对我理解操作系统有很大的帮助. (当然, 如果你不看第一部 ...

  5. CSAPP读书随笔之一:为什么汇编器会将call指令中的引用的初始值设置为-4

    CSAPP,即<深入理解计算机系统:程序员视角>第三版,是一本好书,但读起来确需要具备相当的基本功.而且,有的表述(中译文)还不太直白. 比如,第463页提到,(对于32位系统)为什么汇编 ...

  6. 深入理解计算机中的 csapp.h和csapp.c

    csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载.这是<深入理解计算机系统>配套网站. 在头文件的# ...

  7. CSAPP(前言)

    很久之前就听过有过CSAPP这本书的传闻了,今天终于决定上手这本神作:既然是神作,就要仔细拜读一下,今天看了一下前言部分还真的令人耳目一新,单单是前言部分就让我学习到几个新的知识点: 1.c和Java ...

  8. CSAPP缓冲区溢出攻击实验(上)

    CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...

  9. 读完了csapp(中文名:深入理解计算机系统)

    上个星期最终把csapp看完了. 我买的是中文版的,由于除了貌似评价不错以外,由于涉及到些自己不了解的底层东西,怕是看英文会云里雾里.如今看来,大概不能算是个长处,可是的确可以加快我的看书速度,否则一 ...

  10. CSAPP Lab2: Binary Bomb

    著名的CSAPP实验:二进制炸弹 就是通过gdb和反汇编猜测程序意图,共有6关和一个隐藏关卡 只有输入正确的字符串才能过关,否则会程序会bomb终止运行 隐藏关卡需要输入特定字符串方会开启 实验材料下 ...

随机推荐

  1. [红日安全]Web安全Day3 - CSRF实战攻防

    本文由红日安全成员: Once 编写,如有不当,还望斧正. 大家好,我们是红日安全-Web安全攻防小组.此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字 ...

  2. 如何通过学校系统漏洞注册到 @edu.cn 邮箱账号?

    此文章仅针对我自己学校的系统进行分析,并不代表所有学校的系统都是如此. 我们学校比较"抠",可能是为了节省学校的带宽资源然后禁止学生注册教育邮箱账号.不过像一部电影所说的那样&qu ...

  3. Python 中的集合 --set

    前言 在Python中,我们用[]来表示列表list,用()来表示元组tuple,那{}呢?{}不光可用来定义字典dict,还可以用来表示集合set. 集合 set 集合(set)是一个无序的不重复元 ...

  4. [面试专题]前端需要知道的web安全知识

    前端需要知道的web安全知识 标签(空格分隔): 未分类 安全 [Doc] Crypto (加密) [Doc] TLS/SSL [Doc] HTTPS [Point] XSS [Point] CSRF ...

  5. 使用web写UI, 使用js对接C++项目, 提高开发效率

    ppt资源下载地址https://www.slidestalk.com/s/webui_nodejs_cmdlrx

  6. CSS实现响应式布局

    用CSS实现响应式布局 响应式布局感觉很高大上,很难,但实际上只用CSS也能实现响应式布局要用的就是CSS中的没接查询,下面就介绍一下怎么运用: 使用@media 的三种方法 1.直接在CSS文件中使 ...

  7. js数组冒泡排序、快速排序、插入排序

    1.冒泡排序 //第一种 function bubblesort(ary){ for(var i=0;i<ary.length-1;i++){ for(var j=0;j<ary.leng ...

  8. 前端开发--nginx番外篇

    Centos7下Nginx开发使用(背景: 阿里云ECS Centos7) 安装和启动 安装教程 Centos7安装Nginx实战 需要主意的如下: 文中第四步 4.配置编译参数命令:(可以使用./c ...

  9. Layabox UI 笔记

    1.UI List  官方文档是 https://ldc2.layabox.com/doc/?language=zh&nav=zh-js-3-3-7 通常用List的时候会出现滚动条按钮比例拉 ...

  10. 【01】openLayers 第一个地图

    效果: 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...