网站首页  |   业界社区  |  电信社区  |  技术社区   |  极客社区  |  游戏社区  |  生活社区   |   科技博客  |   同事录
TechWeb-技术社区



标题: [c] 调查论坛中深入了解C的高手有多少
冰红茶
TW中级会员
Rank: 3Rank: 3



UID 80750
精华 4
积分 432
帖子 301
阅读权限 30
注册 2006-8-10
状态 离线
发表于 2008-6-30 11:53 资料 短消息 加为好友
调查论坛中深入了解C的高手有多少

前提,不修改代码!!! ;z*z*U*`-`%i

7}7M9B(t,V%S(~!C d假设你截获了截获了一段编码信息,这些密文是一系列的二进制代码,用16进制的形式表示如下:
,Q4B7B+]!qtech.techweb.com.cn9`.Z6z.d/g;k1B,v
'p9T3W#]9?5w)v

;O#s&Z4V$Z9p/B9? ]tech.techweb.com.cn6363636363636363724646636F6D6F72
;I5C5O(m z.w&h&VTechWeb-技术社区
:X/q/O"q.i%f&[$a466D203A65693A7243646E206F54540A
+@2q*c6x;k'O0c-m,@0y+h!R程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛5s'P3T8t$Y1F7w,B:c,{9K
5920453A54756F0A6F6F470A21643A6F
(t#[)x8O!X2Y%k5~:R(Y
8|1q-g:I2M3E;~"v2~$`594E2020206F776F797275744563200A
,f%N&K:`3h-y程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛
5i*l4U2\.d4G(l;X5f6F786F686E6963736C206765796C656B
#y1B*T/D-E%R3v3t+g8g
8[*Q%O%f7?%t2C3365737420346E20216F74726F5966
3q"F!L5D7y8r
/`.b2a#y)j7565636F202061206C61676374206C6F
Y+n!A$m8i:j"W6r I*s
&`%B6Z)e4y/L程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛20206F74747865656561727632727463 tech.techweb.com.cn1O:a ^(U)j3y

+h8k5`#o/vTechWeb-技术社区6E617920680A64746F69766120646E69 6m9^1}8p$@%z4s
程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛3p+e3t0h;[(L @
21687467630020656C6C786178742078 TechWeb-技术社区,L.W x#l7}%\(c3G4v8x

,@:g%s#H [-a9m.j6578206F727478787863617800783174 TechWeb-技术社区%o#G0d*n2?1T!g*B

#Y3D+S6s2x%V4I程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛虽然你并不知道怎样进行译码以获取其表达的信息含义,但是能否将信息内容破译决定了你的成绩。所以你会尽一切努力进行代码的破译。幸好一个007特工获取到了一部分解码的程序,并将程序放在文件secret.cpp文件中。 /y)K8E*o.W,\
TechWeb-技术社区2u;E1z0E9S1g
阅读这个源程序你可以发现这个译码程序运行时需要输入四个整数参数,如果任意输入一些整数运行,程序或者会异常中断,或者会输出一些莫名其妙的乱码。看来如果输入正确的四个参数就可以得到正确的解码信息,所以这四个整数又叫做“密钥”。虽然007特工没有拿到这四个密钥,但是他在一个桌子上发现了程序解密后的前5个原文,它们是:“From:”。 $}%S&~*p5o

3f5a+L'O8i你的任务就是: "G$Y;z9F9T!m
;f9~5l%D$s+O;X
(1)      破译这段密文; TechWeb-技术社区!E1C1D'd)F.r

+`6u#T0{$|9l'Q程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛(2)      确定四个整数构成的密钥。
!^4t,q0v'S"z/q [-o-R"~'i/k!b9D%T%n
PS:在VC6.0编译环境下,且输入的四个参数在Projiect -> Setting -> Debug -> Program arguments: 中设置,每个key之间有一个空格即可;
4O,U7~"C-y.i
%c&^;O*L#`&s!zTechWeb-技术社区6\"W8G7y.[;F%U

7k(c.b%F$D:pTechWeb-技术社区secret.cpp 源代码:
:x1Z6N1q)h%j,K![+{1l程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛1p/c0D"O'j6_5D6Q*q,f4P&D
#include <stdio.h> +X*v9w#p9W

4_&\2G;b-`6p,Ytech.techweb.com.cn#include <stdlib.h>
:y9Q/m(Y)S K/l7a2_%q
4W0n$o/b"U*@;M;K*mint data [] = { 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛;p:{1h'p*E1b+|.d!V
          0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72, tech.techweb.com.cn2j)C.q(K1e#Z6`.^/|!w
          0x466D203A, 0x65693A72, 0x43646E20, 0x6F54540A,
3j5E;B#?)G$I:B-d.{          0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F, TechWeb-技术社区0D;F#C*Y6y)]1K
          0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
+~!x#O+x:K1]3b"`(n7H          0x6F786F68, 0x6E696373, 0x6C206765, 0x796C656B, 8M2k#K(h6n(q.d
          0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966, tech.techweb.com.cn+{5q&f0J-k't2h&n
          0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
+U9s/c0W+t"h2w1]          0x20206F74, 0x74786565, 0x65617276, 0x32727463,
y%E0v$~)e"_1r){(a          0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69, 1U)h6P:n2o5}
          0x21687467, 0x63002065, 0x6C6C7861, 0x78742078,
7t5W7B5@$L7M1S;{          0x6578206F, 0x72747878, 0x78636178, 0x00783174 *A:z)X'V!G9L
}; 2^4t/e.v.x9r%J K:x#a!h

7X3g"U6}2l9}!c.d7w*qtech.techweb.com.cn
$u!u;s0s/e0o0n,D3hchar message[100];
*^,Z0p"k#J.D&q%Ptech.techweb.com.cn5n*\7l$M7S)j#s
void usage_and_exit(char * program_name) { tech.techweb.com.cn%L5K"P!q3m4b5H0j4Q
    fprintf(stderr, "USAGE: %s key1 key2 key3 key4\n", program_name); 7F)w!w8C;r:t
    exit(1);
6g1z7Y#O$r4k9|%k:z,y,a}
,^6G$r2L1y2D程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛)X;h"F8t:q&K
void process_keys12 (int * key1, int * key2) { 0~ l5Y8E#p3U(I6Q:J
  
7[:O)M1~0q;?6q程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛    *((int *) (key1 + *key1)) = *key2; $x%w0t't0M$r4M/o#X
} 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛"o;V#D6X"@4A(}#F/U9r9t7_

7s7l!e9k9g Hvoid process_keys34 (int * key3, int * key4) {
"H*G"T9}:M5~*\)qtech.techweb.com.cn:h,V }'A:O!m7k"w!P/z
    *(((int *)&key3) + *key3) += *key4; TechWeb-技术社区1U-F4S5g!O8y
} tech.techweb.com.cn/j-B5a*X.J4m

b+]&C&a2@,I,|#](G(HTechWeb-技术社区char * extract_message1(int start, int stride) {
7A2A/Q q%I3g D1Y    int i, j, k; ,i-@8S(N)@
    int done = 0; %m3@%K7W6F5~8G6K*D5f

9G$Y(@#H3T/u;b(]TechWeb-技术社区    for (i = 0, j = start + 1; ! done; j++) {
$X0W!M l E2a程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛        for (k = 1; k < stride; k++, j++, i++) { TechWeb-技术社区*q,k(A(l!o)m*n;\0o

9M1]0i/j5\,S            if (*(((char *) data) + j) == '\0') { 3i7d ]5K"b!`5u
                done = 1; *u'd6c;c2P"u._
                break; ;e(r&S6\5t:n'y
            }
4E;p$k&u9T4X6m5H                           
&J9D6N:i V程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛            message = *(((char *) data) + j);
Z&l4R&w4G(`        } +_8l$A)j5O3C0@
    }
.O'c0b7g#H*~tech.techweb.com.cn    message = '\0';
-I&d5_0c5p/N%R0{:[.e    return message;
5A4_&J!c7Y&n1[9p,P} j7x!~&m4{1h4[5S

/w2L/}'q"B1n7\!^tech.techweb.com.cn程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛,y5p"d)D%^4e1\5X
char * extract_message2(int start, int stride) {
(T;@5B'z3|0}9L-}'f4P    int i, j; tech.techweb.com.cn2a(z0S.|(_'L5T:e

7i$O3x4W s9e2C'g:g7[8@(q0dtech.techweb.com.cn    for (i = 0, j = start;
({$O*Z*|-i6M$L2@1I        *(((char *) data) + j) != '\0'; "U.Q'K*x1f&b
        i++, j += stride)
)R8^"o&x0q.u*g1m        {
7["c9I)Y/o#n8h;kTechWeb-技术社区            message = *(((char *) data) + j);
;h'C/G'w:l$C$N:?6@程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛        }
9X1\,h.j$M)y7@'n:mTechWeb-技术社区    message = '\0';
!P'r&c6T"S+w:S9u    return message; TechWeb-技术社区8w(d%l:?2J+j8c&C,u
} .A'x4^(s;G&h%z6H$j+x
TechWeb-技术社区3s/H"H5`%U6k
int main (int argc, char *argv[]) /N$[2?,O9x%j
{
1^(o&o&A2a/{"}tech.techweb.com.cn    int dummy = 1; #m2J5x"K7}:J0h-D%]
    int start, stride; TechWeb-技术社区,@#F-o!d-\"^*D/H/|"H
    int key1, key2, key3, key4; ,e-Y(s7|"b-G*t8W*U
    char * msg1, * msg2; 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛,]4u6W-w9g!a;V
/q&b6q*g$B'G.b2j2H#H
    key3 = key4 = 0; 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛#`'r,K8n%i2C8j
    if (argc < 3) { tech.techweb.com.cn$i-j(T4u)`;M#V
        usage_and_exit(argv[0]);
%T5C's)g!D E程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛    }
(m'W&Y9Z4X.\)l    key1 = strtol(argv[1], NULL, 0);
8L/P0e*\)f2L程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛    key2 = strtol(argv[2], NULL, 0);
+f+N4k&K5G    if (argc > 3) key3 = strtol(argv[3], NULL, 0);
5m1A)A.W4B&o    if (argc > 4) key4 = strtol(argv[4], NULL, 0); 1})x!i5K/b9G
'w#\#w5l2A%h3m'x&b
    process_keys12(&key1, &key2); tech.techweb.com.cn$e4E0C2f2O+Z6s8g
#_8R'u/F&H(j;g9b
    start = (int)(*(((char *) &dummy))); 6f#j"t%F'J:u6G7Y4B#T
    stride = (int)(*(((char *) &dummy) + 1)); TechWeb-技术社区6X4~+X0W4E&u2X

:N!e9z9D5U+}    if (key3 != 0 && key4 != 0) { 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛/o.T6Y9y%R7M9^%A
        process_keys34(&key3, &key4);
-\;M9X%r9F*M5|)S'n,T&i$f    } %W$r*v+z'c0c(v,p

1v#Q2?6j1s!T    msg1 = extract_message1(start, stride);
*D,M'E6L {
-g#b;U3P+L    if (*msg1 == '\0') { TechWeb-技术社区8x2t(C!B,e+T
        process_keys34(&key3, &key4); 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛0Z/q5Y%L8M
        msg2 = extract_message2(start, stride); tech.techweb.com.cn!}.d t!y2K+o4V
        printf("%s\n", msg2); 程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛2y1R#v9E0}
    }
*_3C)U c*h;?7Q(h    else { 9j#\3c)I/D"],y
        printf("%s\n", msg1); TechWeb-技术社区 y0_%C7l4R&?&m
    } TechWeb-技术社区/^ K%Y!R9p3g'G#D9y

,A5u.S,^'P$T/Q*m9y+e5h8DTechWeb-技术社区    return 0; 0B(w+\ g4n(t-c9p)j2J%{#e
}

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:02 资料 短消息 加为好友
来看看 有难度哦

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:03 资料 短消息 加为好友
还处于初级阶段,这个..

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:03 资料 短消息 加为好友
观望,等待高手出现。

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:03 资料 短消息 加为好友
对于程序secret.cpp,调试过程如下:
   
    1、设置断点,测试出所有变量在内存中的地址。测试结果如下:
          &key1  =  0x0012ff70
          &key2  =  0x0012ff6c
          &key3  =  0x0012ff68
          &key4  =  0x0012ff64
          &start  =  0x0012ff78
          &stride =  0x0012ff74
          &dummy  =  0x0012ff7c
         
    2、对于语句 "process_keys12(&key1, &key2);" 跟踪进入函数体,函数参数key1的值等于主函数里key1的地址(0x0012ff70)。key1所指向的值为主函数里key1的值(第一个密码参数)。显然,这是一个更改某个内存的语句。该内存以主函数里key1的地址为基准,偏移量为key1,即为地址(&key1+key1)。对该地址赋值,其值为主函数里key2的值(第二个密码参数)。
        
        ※所以,函数process_keys12(*key1,*key2)用来修改某些地址所存放的值。
   
    3、语句
            "start =  (int)(*(((char *) &dummy)));"、
            "stride =  (int)(*(((char *) &dummy) + 1));"
        显然,是将地址为&dummy处存放的值赋给start,把地址为(&dummy+1)处存放的值赋给stride。经过查看,可以得出 start = 1,stride = 0 。
        
    4、先跳过接下来的if语句
            if (key3 != 0 && key4 != 0)
            {
                process_keys34(&key3, &key4);
            }
      
      接着看下面的语句:
                msg1 = extract_message1(start, stride);
      进入函数体后,发现,这是将数组data的某些项放到msg1里。但是,这里的两层
for循环,细心注意就会发现,以现在start和stride的值,根本就是一个死循环。
      因为第二层循环里( k < stride )一直为假,如果进不去第二层循环,那么第
      一层循环!done一直为真,程序进入死循环。
      
      ※由此,我们可以判断,要让程序得以正确运行,必须更改start和stride的值。
      
      那么,在哪里改呢?只能在这个函数调用之前改。进一步,刚才在 2 中提到过,
      函数process_keys12()可以用来更改某些地址所存放的值,而且,在函数
      extract_message1()之前,也调用了函数process_keys12()。
      
      ※故而,我们完全有理由相信,函数process_key12()应该是用来更改start和
      stride的值的。
      
      具体怎么修改,可以简单分析一下:
      假如直接在start和stride的地址上进行修改,那么函数process_key12()调用
      后,接着又是对start和stride进行赋值的语句:
          "start =  (int)(*(((char *) &dummy)));"
            "stride =  (int)(*(((char *) &dummy) + 1));"
        这么一来,函数process_key12()就做了无用功。那么,理所当然的我们能想到,
        应该间接来修改start和stride的值。联系那两个对start和stride的赋值语句,
        很容易能想到要是改掉dummy的值不就行了?
        
        ※所以,我们得出,process_key12()是用来修改dummy的值的。
   
    5、下面讨论一下该怎么修改dummy的值:
        
        由 2 我们知道,process_key12()可修改地址为(&key1+key1)的内存单元的
        值。改后的值为key2。 所以,&key1+key1 = &dummy;由 1 知道,
        &key1 = 0x0012ff70 , &dummy  =  0x0012ff7c 。所以,key1的值应该为0xc,
        即 12 。
        但设置好参数key1 = 12 后,我们发现&key1+key1 = 0x0012ffa0 ; 怎么回事呢?
        这么算下来,key1好像变成了48(0x0012ffa0-0x0012ff70 = 0x30)。这正好是我
        们想要的12的四倍。原来,这里地址相加减时,key1当作地址算时,应该是乘以4再相加,因为整型占四个字节。所以,我们应该将key1的值设为3。
        
        ※故,至此,key1 = 3 。
        
        我们虽然通过设置key1的值找到了dummy的内存地址,那么到底该将dummy改成多少呢?
        现在看看函数体:
              char * extract_message1(int start, int stride)
              {
                    int i, j, k;
                    int done = 0;

                    for (i = 0, j = start + 1; ! done; j++)
                    {
                          for (k = 1; k < stride; k++, j++, i++)
                          {

                            if (*(((char *) data) + j) == '\0')
                            {
                            done = 1;
                            break;
                          }
                          message = *(((char *) data) + j);
                        }
                    }
                    message = '\0';
                    return message;
              }
        要是把data的值要原原本本的放到数组message里,那么start的值为-1、0
        或者更大,stride的值显然不能取0、1;故可试试2或者3。
        这里为了测试数据是否正确,可以先将函数体里的start换成-1,stride
        换成2。然后运行一下程序,发现输出为:

                cccccFrm:mri d
                T:
                u
                ood Nootr
                chxsie kls3n t!fooe  cao t exvacr at
                aiidghe
                Press any key to continue
              
        看上去是乱码,怎么回事呢?
        这说明我们取的start和stride的值不恰当。那么试试stride=3呢?因为stride
        =2的时候是隔一个字母取一个,为3时隔一个取两个字母。这样,输出结果为:
              
              ccccccFFroo:mF:i nC
              ToE
              oT
              oo:d  Yoo ur
              Ehxocieglklye3n4tt! Yoocu  gaoltt  exvrecr2yatdhaiondgt!e
              Press any key to continue
              
        那么继续试试start = 0 、stride = 3呢?结果为:
              
              ccccccFrom: Friend
              To: You
              Good! Now try choosing keys3,4 to force a call to extract2 and
              avoid the call to extract1
              Press any key to continue
              
        嗯,这样就好了,再把前面多于的c去掉就完整了。所以我们可以得出:

        ※ start = 9,stride = 3。
        
        那怎么将得到的数字写入相应的位置呢?
        从两个对start和stride的赋值语句可以看出,这两个变量存放在连续的地址上。
        既然我们找到了起始地址0x0012ff7c,那么我们希望从这里开始存入数据:
                        0x0012ff7c  09        ( start的值 )
                        0x0012ff7d  03        ( stride的值)
        这样,我们要写入0x0309。转换为十进制为 777,即key2的值。
        
        ※所以,我们得到key2 = 777。

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:04 资料 短消息 加为好友
6、将参数设置好,运行后,就会出现如下输出:
   
              From: Friend
              To: You
              Good! Now try choosing keys3,4 to force a call to extract2 and
              avoid the call to extract1
              Press any key to continue

        这说明key1、key2都正确了。下面我们找key3、key4。
        先随便给key3、key4设置个值。比如key3 = 3 ,key4 = 4。
        根据提示,我们要避免对函数extract_message1()的调用。换句话说,就是程序
        要跳过extract_message1()语句。即:
        执行完:
                if (key3 != 0 && key4 != 0)
                {
                  process_keys34(&key3, &key4);
              }
                        (语句一)
               
        后,立即转到:
                if (*msg1 == '\0')
                {      
                  process_keys34(&key3, &key4);
                  msg2 = extract_message2(start, stride);
                  printf("%s\n", msg2);
              }
                          (语句二)
              
    语句执行。
        这只能修改内存中的指令内存地址了。
        显然,修改这个数据应该由process_keys34()来完成。
   
    7、既然要修改指令内存地址,那么必须得找到语句一和语句二的指令地址。
        通过反汇编:
        
                111:          process_keys34(&key3, &key4);
                0040137E  lea        eax,[ebp-1Ch]
                00401381  push        eax
                00401382  lea        ecx,[ebp-18h]
                00401385  push        ecx
                00401386  call        @ILT+25(process_keys34) (0040101e)
                0040138B  add        esp,8
        
        此时,我们观察ESP的值,ESP=0012FF0C。这是堆栈的栈顶指针。调用函数
        process_key34()时,要将局部变量压栈,接着是断点处的指令地址
        (0040138B)。所以我们得到函数返回时下一条指令的地址。而我们要做的,
        就是改掉这个地址(0040138B)。在内存查看窗口,我们输入ESP的值
        (0012FF0C);然后看看比它稍低的内存地址。可以看到:
        
                0012FEFC  CC CC CC CC  烫烫
                0012FF00  80 FF 12 00  ....
                0012FF04  8B 13 40 00  ..@.
                0012FF08  68 FF 12 00  h...
                0012FF0C  64 FF 12 00  d...
                0012FF10  00 00 00 00  ....
        
        注意在0012ff0c上存放的数据是0012ff64,这是什么呢?可以查看一下:
                0012FF64  04 00 00 00  -...
        是4,即key4的值。同样,在0012ff68存放的是3,即key3的值。接着的
        0040138B存放的便是我们想要的指令地址,即调用函数返回后应该继续执行的语
        句的地址。而我们也能很容易的看到,这个地址被存在了地址为0012ff04的位置
        上。
        
        ※这样,我们找到了两个地址,即在0012ff04上存放的指令地址0040138b
        
    8、下面我们还要找到一个地址,就是我们想让程序跳到的那个位置。
        在反汇编的状态下,找到:
        
              117:          process_keys34(&key3, &key4);
                004013AB  lea        eax,[ebp-1Ch]
                004013AE  push        eax
                004013AF  lea        ecx,[ebp-18h]
                004013B2  push        ecx
                004013B3  call        @ILT+25(process_keys34) (0040101e)
                004013B8  add        esp,8
              118:          msg2 = extract_message2(start, stride);
         
        注意,这是语句"process_keys34(&key3, &key4);"反汇编得来的。初看起来,这个
        语句没什么用。因为我们想要的只是让程序执行
                    "msg2 = extract_message2(start, stride);"
        但是,请看反汇编代码:
        
                111:          process_keys34(&key3, &key4);
                0040137E  lea        eax,[ebp-1Ch]
                00401381  push        eax
                00401382  lea        ecx,[ebp-18h]
                00401385  push        ecx
                00401386  call        @ILT+25(process_keys34) (0040101e)
                0040138B  add        esp,8
               
        在调用函数后,如果我们修改了下一条指令的地址,那么语句
                      "0040138B  add        esp,8"
        将不能执行。这将导致esp不能回到函数调用前的栈顶。那么后面的程序执行也将会出现错误。所以我们还得要执行
"add        esp,8"
        那么,这样看来,语句
"117:          process_keys34(&key3, &key4);"
就用的恰到好处,请看这句语句反汇编的最后一行,
"004013B8  add        esp,8"
        刚好将esp恢复到初始状态。所以我们应该让程序跳到这里(004013B8)。
        这样,我们想要的地址都找到了。我们要做的事是:
        
        ※找到内存为0012ff04的位置,将其上存放的数据改成004013B8。
   
    9、下面,我们将用函数process_keys34()来修改内存,达到我们的目的。
        看一下process_keys34()的函数体:
                  *(((int *)&key3) + *key3) += *key4;
        通过查看,我们可以知道,&key3 = 0x0012ff08。而我们要修改的地址为0x0012ff04
        由上面求key1、key2的方法,可以知道,*key3 = (0x0012ff04-0x0012ff08)/4 = -1
        所以主函数里key3 = -1。
        现在将key3的值设成-1,然后调试。由7可以知道,0x0012ff04上存放的是0040138b
        那么很容易能计算出*key4的值:
        *key4 = 004013B8-0040138B = 002D  转换为十进制为*key4 = 45。
        
        ※所以,key3 = -1 ,key4 = 45。
   
    10、设置参数的值: key1 = 3,key2 = 777, key3 = -1,key4 = 45。
        运行结果为:
        
                          From: CTE
                          To: You
                          Excellent!You got everything!
                          Press any key to continue
                          
        至此,所有调试工作都完成了!

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:05 资料 短消息 加为好友
出于初级阶段,进来看看高手的解题艺术

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:08 资料 短消息 加为好友
这就能判断谁是C语言高手?
这是你们行业里面的东西,和C语言关系不大

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:08 资料 短消息 加为好友
N久之前在论坛上就看到了

引用 回复 顶部
游客
未注册









发表于 2008-7-4 11:08 资料 短消息 加为好友
在VS2005下编译 key1和dummy的地址相差不是12字节 这和编译器也有关吧

引用 回复 顶部
查看积分策略说明快速回复主题
选项 标题 Smilies
禁用 URL 识别
禁用 Smilies
禁用 Discuz!代码
使用匿名发帖
使用个人签名
接收新回复邮件通知
内容





当前时区 GMT+8, 现在时间是 2008-8-30 14:53
京ICP证060517号

本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.5.0 © 2001-2008 Comsenz Inc.
Processed in 0.103287 second(s), 7 queries

清除 Cookies - 联系我们 - TechWeb.com.cn - Archiver - WAP