精华内容
下载资源
问答
  • <div><ul>去除单字母变量</li><li>修复函数返回值语法错误</li><li>保留current_weixin_token</li></ul>该提问来源于开源项目:lanrion/weixin_rails_middleware</p></div>
  • gdb 修改函数返回值

    千次阅读 2013-11-19 07:55:49
    昨天在测试同事的一段代码时,返回值没有保存到变量中,而是直接进行判断的,类似这样: int check_state(); // a function from other library, didn't have it's definition, just a declaration. int func1...

    昨天在测试同事的一段代码时,返回值没有保存到变量中,而是直接进行判断的,类似这样:

        int check_state();   // a function from other library, didn't have it's definition, just a declaration.  
          
        int func1()  
        {  
            if(!check_state())  
                return 0;  
            else  
                return -1;  
        }  
          
        int parent_func()  
        {  
            if (!func1())  
            {  
                // do something, code segment 1  
                ......  
                ......  
                return -1;  
            }  
          
            // do something, code segment 2  
            ......  
            ......  
            return 0;  
        }  
      由于check_state()是来自另一个.a文件的函数,所以无法改变它的返回值,每次它都返回非0值(导致func1()每次都返回-1。),但是我想测试func1()返回0时代码的执行情况。同事在此处并没有用一个变量来存储这个返回值,所以无法通过设置变量的值达到效果。

        每个C语言的函数,都会通过寄存器返回值,所以我们可以通过修改func1()中寄存器的值,达到我们的测试目的。

        写一个简单的测试代码来说明用法(检测输入参数是否大于10):


        #include <stdio.h>  
        #include <stdlib.h>  
        int func1(int input)  
        {  
                if(input < 10)  
                        return -1;  
                else  
                        return 0;  
        }  
        int main(int argc, char *argv[])  
        {  
                int input_val = 0;  
                if(argc < 2)  
                {  
                        printf("Need argument./n");  
                        return -1;  
                }  
                input_val = atoi(argv[1]);  
                if(func1(input_val))  
                        printf("Input numeric is little than 10./n");  
                else  
                        printf("Input numeric is bigger than 10./n");  
                return 0;  
        }  

    编译:

    ~# gcc -g -Wall main.c -o main

     

    测试过程:

    ~# gdb main

    GNU gdb Fedora (6.8-37.el5)
    Copyright (C) 2008 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i386-redhat-linux-gnu"...
    (gdb) b main
    Breakpoint 1 at 0x80483e9: file main.c, line 14.
    (gdb) r 7
    Starting program: /root/program/testgdb/main 7

    Breakpoint 1, main (argc=2, argv=0xbf89e694) at main.c:14
    14              int input_val = 0;
    (gdb) n
    15              if(argc < 2)
    (gdb)
    20              input_val = atoi(argv[1]);
    (gdb)
    21              if(func1(input_val))
    (gdb) s      --------------要进入函数内
    func1 (input=7) at main.c:6

    6               if(input < 10)
    (gdb) n
    7                       return -1;
    (gdb) disassemble   ---- 反编译一下当前函数
    Dump of assembler code for function func1:
    0x080483b4 <func1+0>:   push   %ebp
    0x080483b5 <func1+1>:   mov    %esp,%ebp
    0x080483b7 <func1+3>:   sub    $0x4,%esp
    0x080483ba <func1+6>:   cmpl   $0x9,0x8(%ebp)
    0x080483be <func1+10>:  jg     0x80483c9 <func1+21>
    0x080483c0 <func1+12>:  movl   $0xffffffff,-0x4(%ebp)
    0x080483c7 <func1+19>:  jmp    0x80483d0 <func1+28>
    0x080483c9 <func1+21>:  movl   $0x0,-0x4(%ebp)
    0x080483d0 <func1+28>:  mov    -0x4(%ebp),%eax  ---- 返回值将保存到eax寄存器中
    0x080483d3 <func1+31>:  leave  
    0x080483d4 <func1+32>:  ret    
    End of assembler dump.
    (gdb) i r  ---- 查看当前寄存器的值,主要是eax,此时还未执行"return -1"
    eax            0x7      7
    ecx            0x0      0
    edx            0x0      0
    ebx            0x9f8ff4 10457076
    esp            0xbf89e5c4       0xbf89e5c4
    ebp            0xbf89e5c8       0xbf89e5c8
    esi            0x8b0ca0 9112736
    edi            0x0      0
    eip            0x80483c0        0x80483c0 <func1+12>
    eflags         0x293    [ CF AF SF IF ]
    cs             0x73     115
    ss             0x7b     123
    ds             0x7b     123
    es             0x7b     123
    fs             0x0      0
    gs             0x33     51
    (gdb) n
    10      }
    (gdb) i r   ----- 查看当前寄存器的信息,此时已执行"return -1",eax的值也变成了-1,函数退出后修改
    eax            0xffffffff       -1
    ecx            0x0      0
    edx            0x0      0
    ebx            0x9f8ff4 10457076
    esp            0xbf89e5c4       0xbf89e5c4
    ebp            0xbf89e5c8       0xbf89e5c8
    esi            0x8b0ca0 9112736
    edi            0x0      0
    eip            0x80483d3        0x80483d3 <func1+31>
    eflags         0x293    [ CF AF SF IF ]
    cs             0x73     115
    ss             0x7b     123
    ds             0x7b     123
    es             0x7b     123
    fs             0x0      0
    gs             0x33     51
    (gdb) set $eax = 0    ---- 通过set命令修改eax的值,与变量不同,修改寄存器的值时,需要在寄存器名称前加'$'
    (gdb) i r    ---- 再次查看eax的值,eax已变为0.
    eax            0x0      0
    ecx            0x0      0
    edx            0x0      0
    ebx            0x9f8ff4 10457076
    esp            0xbf89e5c4       0xbf89e5c4
    ebp            0xbf89e5c8       0xbf89e5c8
    esi            0x8b0ca0 9112736
    edi            0x0      0
    eip            0x80483d3        0x80483d3 <func1+31>
    eflags         0x293    [ CF AF SF IF ]
    cs             0x73     115
    ss             0x7b     123
    ds             0x7b     123
    es             0x7b     123
    fs             0x0      0
    gs             0x33     51
    (gdb) n    ----  继续执行代码,可看到程序输出"Input numeric is bigger than 10."。我们通过修改寄存器的值,对程序代码的执行过程进行了控制。
    main (argc=2, argv=0xbf89e694) at main.c:24
    24                      printf("Input numeric is bigger than 10./n");
    (gdb) c
    Continuing.
    Input numeric is bigger than 10.

    Program exited normally.
    (gdb)

     

        对于一些小程序,这么测试还是很有效的。


    展开全文
  • Spring AOP修改函数返回值

    万次阅读 2013-02-24 20:56:47
    最近boss叫我用spring aop做一个试验,说是之后一个新项目要用到,大体需求如下:拦截某个函数返回值,并修改之。  因为之前我对AOP的认识只是停留在上课时老师跟我们传授的理论阶段,从未写过代码实践过,...

    最近boss叫我用spring aop做一个试验,说是之后一个新项目要用到,大体需求如下:拦截某个函数的返回值,并修改之。

        因为之前我对AOP的认识只是停留在上课时老师跟我们传授的理论阶段,从未写过代码实践过,因此这次我花了一定的时间去做了这个试验。一开始打算上网直接查找相关代码,但是发觉都没有达到我预期的效果,于是决定自己写一个。一开始我打算用后置增强来解决,但是发现只能获取返回值,并不能改变它,之后在stackOverflow问了一下,经过一个网友的提示,终于fix掉了,核心是用环绕增强和ProceedingJoinPoint,废话少说,直接贴代码

    定义目标业务类

    public class AopDemo implements IAopDemo{
    
    	public String doSth(String task){
    		System.out.println("do somthing.........."+task);
    		return task;
    	}
    定义切面,参数ProceedingJoinPoint 通过直接打印pjp,会看到控制台输出一句execution(String com.toby.aop.IAopDemo.doSth(String)),说明pjp是当前被调用的切点方法的引用

    public class Listener {
    
    	public Object around(ProceedingJoinPoint pjp) throws Throwable{
    		System.out.println("beginning----"); 
    		Object object = pjp.proceed();    //运行doSth(),返回值用一个Object类型来接收
    		object = "Mission Two";   //改变返回值
    	    System.out.println("ending----");
    		return object;    
    	}
    }
    配置xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xmlns:util="http://www.springframework.org/schema/util"
    		xmlns:context="http://www.springframework.org/schema/context"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xmlns:aop="http://www.springframework.org/schema/aop"
    		
    		xsi:schemaLocation="http://www.springframework.org/schema/beans 
    			http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    			http://www.springframework.org/schema/tx  
                http://www.springframework.org/schema/tx/spring-tx.xsd  
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    			http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
    
    	<bean id="aopDemo" class="com.toby.aop.AopDemo"/>
    	<bean id="listener" class="com.toby.aop.Listener"/>
        <aop:config>
        	<aop:aspect id="myListener" ref="listener">
     <aop:pointcut expression="execution(* com.toby.aop.AopDemo.*(..))" id="listenerCut"/>
        		
        		 <aop:around method="around" pointcut-ref="listenerCut"/> 
        	</aop:aspect> 
        </aop:config>	
    </beans>
    测试

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context-common.xml");
    		IAopDemo demo = (IAopDemo)context.getBean("aopDemo");
    		System.out.println(demo.doSth("Mission One"));

    程序运行结果 

     

        beginning----

        do somthing..........Mission One

        ending----

        Mission Two

     

       调用doSth()后,@Around定义的around()方法里通过拦截返回值"Mission One",并修改为“Mission Two”返回,也就是说,doSth的返回值最后其实是around()的返回值


    如果有更好的方法,也欢迎赐教,大家互相学习!




    展开全文
  • 首先我们先分析(IDA和Hopper都要分析啊)一下二进制文件,这里我要把[SMLicenseManager verifyLicenseWithName:code:]函数返回值定为true,所以直接找到这个函数返回的地方: 先看Hopper: rax寄存器是返回值...

    先说一下背景。。本人用的Hopper Disassembler v4的Demo版本,因此只能使用Modify -> Assemble Instruction功能,但是不能导出二进制文件。但是手上又有IDA Pro的绿色版。。所以只能Hopper改完之后,再通过IDA Pro导出二进制文件。

    当然大能(逆向的老手)可以直接用IDA的Patch program来改,但是因为Hopper Disassembler改Mac或者iOS的程序比较简单,所以我就两边结合来改了。

    首先我们先分析(IDA和Hopper都要分析啊)一下二进制文件,这里我要把[SMLicenseManager verifyLicenseWithName:code:]函数的返回值定为true,所以直接找到这个函数返回的地方:

    先看Hopper:
    在这里插入图片描述

    rax寄存器是返回值寄存器,相当于被放在rax里的值最后都会被return rax;。
    rax在第2行出现过一次,mov指令可以理解为赋值语句,意义是将qword [_objc_release_10014e238]的值赋予rax。
    我们不用管qword [_objc_release_10014e238]是什么,我们要的结果是return true,也就是return 0x01,只需要确保在ret指令的时候rax的值是0x01即可。
    因此选中mov rax, qword [_objc_release_10014e238]一行,选择Modify-Assemble Instruction,输入如下指令:

    mov        rax, 0x1
    

    然后函数会变为:
    在这里插入图片描述

    此时选择直接查看二进制页面,发现二进制做了如下修改:
    在这里插入图片描述

    这里的地址要靠自己数了。。每一行的开头都是起始地址,每走一个数(45这样的算一个数)地址加1。

    然后进入IDA Pro,先查看上面修改的那条指令的地址:
    在这里插入图片描述

    然后进入Hex页面,查看二进制:
    在这里插入图片描述

    对比两边哪里有修改,证明应该改哪里。因此我们直接在IDA中选择Edit-Patch Program-Change byte,然后修改成跟Hopper Disassembler一样的二进制即可:
    在这里插入图片描述

    这里要注意你的光标位置,Change byte的起始位置是根据你的光标位置来的,所以光标位置一定要正确
    然后查看IDA View,修改成功:
    在这里插入图片描述

    总结一下:建议大家有钱还是直接买正版Hopper Disassembler,$99(涨价了,以前是$89,不知道以后还会不会涨),比IDA便宜了太多。。也免得两边切换。

    展开全文
  • } } 代码很清晰做了一个if判断,函数securityCheck来验证输入的验证码是否正确,正确就进入下个Activity ,不正确提示 验证码校验失败。我们只要HOOK 函数securityCheck()无论传入什么值都返回true。 3、关门放...

    本期用到 :python+frida+模拟器
    如果没布置Frida环境可以跳转此文: Hook神器: frida超详细安装教程

    一、分析

    APK:AliCrackme.apk
    阿里安全比赛上的题目,目标无壳,一个简单的密码校验软件,只有输入正确的密码才能进入,错误密码会提示检验失败。
    在这里插入图片描述

    2、JADX分析代码逻辑

    直接搜索“验证码校验失败”锁定代码位置。
    代码如下:

    package com.yaotong.crackme;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
        public Button btn_submit;
        public EditText inputCode;
    
        public native boolean securityCheck(String str);
    
        /* access modifiers changed from: protected */
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            getWindow().setBackgroundDrawableResource(R.drawable.bg);
            this.inputCode = (EditText) findViewById(R.id.inputcode);
            this.btn_submit = (Button) findViewById(R.id.submit);
            this.btn_submit.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    if (MainActivity.this.securityCheck(MainActivity.this.inputCode.getText().toString())) {
                        MainActivity.this.startActivity(new Intent(MainActivity.this, ResultActivity.class));
                        return;
                    }
                    Toast.makeText(MainActivity.this.getApplicationContext(), "验证码校验失败", 0).show();
                }
            });
        }
    
        static {
            System.loadLibrary("crackme");
        }
    }
    

    代码很清晰做了一个if判断,函数securityCheck来验证输入的验证码是否正确,正确就进入下个Activity
    ,不正确提示 验证码校验失败。我们只要HOOK 函数securityCheck()无论传入什么值都返回true。

    3、关门放Frida

    #-*- coding:utf-8 -*-
    import frida, sys
    def on_message(message, data):
        if message['type'] == 'send':
            print("[*] {0}".format(message['payload']))
        else:
            print(message)
            
    jscode = """
    Java.perform(function () {    
        //调用类
        //包+类
        var fun = Java.use('com.yaotong.crackme.MainActivity');
        //函数及传参
        fun.securityCheck.overload('java.lang.String').implementation = function(str1) {
            send("return true");
            return true;
        };
    });
    
    """
    process = frida.get_usb_device().attach('com.yaotong.crackme')
    script = process.create_script(jscode)
    script.on('message', on_message)
    print('[*] Hook Start Running')
    script.load()
    sys.stdin.read()
    

    启动模拟器上的frida-sever,然后随意输入密码,校验成功。

    在这里插入图片描述
    如果想要自己动手练习的话,可以关注公众号回复: hookjava
    获取练习的APK

    console.log("公众号:虫术")
    console.log("wx:spiderskill")
    欢迎大家前来交流
    
    展开全文
  • spring AOP 之 获取 被切函数参数 被切函数返回值 以及 修改被切函数返回值
  • 有没有一种常见的方法可以获得这些函数返回值,并只对它们执行一个额外的操作,如pformat?是的我可以生成如下的新功能:func = ... # func can be got using getattr by namedef wrapper(*arg, **kw):da...
  • 如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符串或者元组)的引用,就不能直接修改原始对象--...
  • Java 函数返回值修改

    2015-05-29 10:59:39
    现在假设有一个类Class A{ public static get_data Int (){ return a; } } ...如果在class B 调用get_data方法得到a,并且在class B中对a做一些处理,如何使B中处理完的a使A...其实就是想问如何修改静态方法的返回值
  • I wrote a decorator that gets the runtime of the program, but the function return value becomes Nonetype.def gettime(func):def wrapper(*args, **kw):t1 = time.time()func(*args, **kw)t2 = time.time()t =...
  • 函数返回值

    2019-06-24 18:19:46
    //求输入x[]求修改后的x[];#include <stdio.h>#include <stdlib.h>void *bbb(int *p1){ int i = 0; while(i<4) { *p1+1=1; *p1++; i++; }}int main(void){ int a[4]={1,2,3,4}; bbb(a); int i=0; ...
  • 引用作为函数返回值

    2020-12-22 22:40:27
     1、在函数内部会对此参数进行修改  2、提高函数调用和运行效率  关于第一点,都知道C++里提到函数会提到形参和实参。如果函数的参数实质是形参,不过这个形参的作用域只是在函数体内部,也是说实参和形参是...
  • 一个函数的执行结果要返回给调用者,除了使用 return 功能,还有一种办法,那就是以引用的形式传递参数,然后在函数内部修改这个参数的值。前一种方法往往只能返回一个值,如果我们的函数执行结果具有多种数据,便...
  • 函数返回值 函数参数 一、引子 1.不用函数会引发什么问题?  代码的组织结构不清晰,可读性差;  遇到重复的功能只能重复编写实现代码,代码冗余;  功能需要扩展的时候,需要找出所有实现该功能的...
  • 2、如果这个方法没有修改区块数据,那直接可以返回值。 例子 pragma solidity ^0.4.25; contract Assert{ } contract TestReturn { Assert sig ; function check() public returns(uint256) { sig = ...
  • 指针作为函数返回值

    2020-12-03 19:49:27
    函数返回值也可以返回指针 double*Show(double); { printf(“数值:%lf\n”,n); return &n; } double d=45.6; double*p=Show(d); printf(“d的地址=%d\n”,&d); printf(“p=%d\n”,p); 此下为错误示范 *p=456...
  • 函数返回值作为左值问题

    千次阅读 2019-05-05 20:45:55
    C++语言的函数返回值类型可以分为内部类型和自定义类型两大类。 如果函数返回内部类型并且希望返回值可以作为左值(即可以放在赋值操作符左边的),那就必须返回引用类型。 而在函数返回自定义类型(即返回类类型)...
  • const用于修饰函数时,一般是const修饰类的成员函数(函数定义体),表示在函数体中成员变量不能改变; 其函数形式为:int ff(void)...又如给"指针传递"的函数返回值加const,则返回值不能被直接修改,且该返回值只能
  • 函数返回值时会产生一个临时变量作为函数返回值的副本,而返回引用时不会产生值的副本。 T f(); 返回一般的类类型,返回的类类型不能作为左值,但返回的类类型可以直接调用成员函数来修改,如function().set_Value()...
  • C++函数返回值

    2020-03-28 22:50:33
    只能由一个返回,那么如何返回多个? 1、返回一个数组的首地址,那么可以把整个数组的元素返回,内定义数组 ...2、传入指针,在函数修改指向的数组等,外定义数组 double a[2]; f(a) void f(double *a) { ...
  • const用于修饰函数时,一般是const修饰类的成员函数(函数定义体),表示在函数体中成员变量不能改变; 其函数形式为:int ff(void)...又如给"指针传递"的函数返回值加const,则返回值不能被直接修改,且该返回值

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,072
精华内容 2,028
关键字:

修改函数返回值