#include <stdio.h>
#include <stdlib.h>
int prologue [] = {
0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
0x20206F74, 0x74786565, 0x65617276, 0x32727463,
0x594E2020, 0x206F776F, 0x79727574, 0x4563200A
};
int data [] = {
0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
0x466D203A, 0x65693A72, 0x43646E20, 0x6F54540A,
0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
0x6F786F68, 0x6E696373, 0x6C206765, 0x796C656B,
0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
0x20206F74, 0x74786565, 0x65617276, 0x32727463,
0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
0x21687467, 0x63002065, 0x6C6C7861, 0x78742078,
0x6578206F, 0x72747878, 0x78636178, 0x00783174
};
int epilogue [] = {
0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
0x20206F74, 0x74786565, 0x65617276, 0x32727463
};
char message[100];
void usage_and_exit(char * program_name) {
fprintf(stderr, "USAGE: %s key1 key2 key3 key4/n", program_name);
exit(1);
}
void process_keys12 (int * key1, int * key2) {
*((int *) (key1 + *key1)) = *key2;
}
void process_keys34 (int * key3, int * key4) {
*(((int *)&key3) + *key3) += *key4;
}
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[i] = *(((char *) data) + j);
}
}
message[i] = '/0';
return message;
}
char * extract_message2(int start, int stride) {
int i, j;
for (i = 0, j = start; *(((char *) data) + j) != '/0'; i++, j += stride)
{
message[i] = *(((char *) data) + j);
}
message[i] = '/0';
return message;
}
int main (int argc, char *argv[])
{
int dummy = 1;
int start, stride;
int key1, key2, key3, key4;
char * msg1, * msg2;
key3 = key4 = 0;
if (argc < 3) {
usage_and_exit(argv[0]);
}
key1 = strtol(argv[1], NULL, 0);
key2 = strtol(argv[2], NULL, 0);
if (argc > 3) key3 = strtol(argv[3], NULL, 0);
if (argc > 4) key4 = strtol(argv[4], NULL, 0);
process_keys12(&key1, &key2);
start = (int)(*(((char *) &dummy)));
stride = (int)(*(((char *) &dummy) + 1));
if (key3 != 0 && key4 != 0) {
process_keys34(&key3, &key4);
}
msg1 = extract_message1(start, stride);
if (*msg1 == '/0') {
process_keys34(&key3, &key4);
msg2 = extract_message2(start, stride);
printf("%s/n", msg2);
}
else {
printf("%s/n", msg1);
}
return 0;
}
要求:根据此程序解出key1,key2,key3,key4
下面我给出一种解法:
Unix_lab_10_secret
0212679,张安春
首先在gdb下打印data的值
(gdb)print (char*)data
由于由题意可知,密文的开头为From,所以在此data中找到F开头的位置为9、10、19三处,又由程序可知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[i] = *(((char *) data) + j);
}
}
j每连续加(stride-1)次并给message赋值,然后就跳过一个字符,由此并根据data值,得出F为位置10处,此时start为9,stride为3。由于start和stride是由dummy得到的,为0x0309所以要在process_keys12中通过key1,key2改变dummy的值:由于key1与dummy的地址相差3个int,所以key3=3, 此时算出key4=777,设置
args为3 777得出结果如下:
(gdb)set args 3 777
(gdb)set args 3 777
(gdb)run
(gdb)run
得出正确结果
得出正确结果
From friend
From friend
To you
To you
now try choosing key3,key4 to force a call to extract2 and avoid the call to extract1
now try choosing key3,key4 to force a call to extract2 and avoid the call to extract1
下面推key3,key4
1、通过改变data值,使process_keys12函数返回一个空值:
先随便设定key3,key4的值,在process_key34中设置断点,打印:
(gdb)p/a data[2]
$6=0x72464663
(gdb)p/a &data[2]
$7=0x8060e28<data+8>
(gdb)p/a &key3
$8= (int **)0x8047c4c
由此计算出data[2]和key3的地址相差0x191dc,为102876,为25719个int,同时计算出要使第十位为0的话需要将key4改为0x0ba0000,即12189696此时带入发现并没有通过,看来地址的改变跟key3,key4值也有关,此时再设断点,发现key3的地址为0x 8047c40,相差0x 0c此时应当把25719改为:25722,此时测试通过!
(gdb)set args 3 777 25722 12189696
(gdb)r
得出正确结果
From:CTE
To:You
Execellent!You got everything!
2、通过改变返回值地址跳过一段程序
使key3为-1,此时(((int *)&key3) + *key3)即为返回值地址,可利用此跳过一段程序
由上面可以得到前一次返回地址是0x80ae7,后后一次返回地址是0x8050b 1a,相差51,所以key4应当设为51,此时带入结果也通过!