Any solution to this puzzle !

N

Nitin

Hi All,

Consider the following code snippet:

------------------------------------------

#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
}

int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
------------------------------------------

apart from the trivial pre-processor trick like this:

#define printf(a,i) printf(a,2*i)

is there any way to achieve it ?

Thanks.
 
E

Emmanuel Delahaye

Nitin wrote on 16/07/05 :
#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
}

int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
is there any way to achieve it ?
Not to my knowledge. You need a parameter (int *) and to pass the
address of i (&i).

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"
 
M

Malcolm

Nitin said:
#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
}

int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
------------------------------------------

apart from the trivial pre-processor trick like this:

#define printf(a,i) printf(a,2*i)

is there any way to achieve it ?
A subroutine doesn't have any access to the caller's local variables.

However you can give it such access by passing them as pointers.

void change2(int *iptr)
{
/* do anything you wnat with the value you are passed */
printf("d", *iptr);
*iptr = 2;
}
 
K

Keith Thompson

Nitin said:
#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
}

int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
------------------------------------------

apart from the trivial pre-processor trick like this:

#define printf(a,i) printf(a,2*i)

is there any way to achieve it ?

Fortunately, no.
 
T

Tim Woodall

Hi All,

Consider the following code snippet:

------------------------------------------

#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
}

int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
------------------------------------------

apart from the trivial pre-processor trick like this:

#define printf(a,i) printf(a,2*i)

is there any way to achieve it ?

No.

=====================================

but ...

tim@feynman:~/c$ gcc -Wall -ansi -pedantic -o x x.c
/tmp/ccca0IUM.o(.text+0x20): In function `change':
: warning: the `gets' function is dangerous and should not be used.

tim@feynman:~/c$ ./x
Please enter your password
11111111
Password OK
5
^ This is your i

tim@feynman:~/c$ ./x
Please enter your password
12345678
FAILED
^^^^^^ This is what supposed to happen if you give the wrong password.

tim@feynman:~/c$ ./x
Please enter your password
6666666666666666666666666666D
Password OK
10
^^ This is your i.

This is a very simple stack smashing attack. _Anything_ can happen, what
happens in practice is that an attacker crafts their attack so that the
"anything" becomes what the attacker wants.


===================== bad code follows =====================
The third example given above will probably _NOT_ work the same on your
system if you compile this code. That's what invoking undefined
behaviour means. (I have carefully "crafted" this code to make the
attack easy with my compiler on my system. I suspect that the "attack" is
possible on most systems but you may end up having to do a full stack
smash attack (see Smashing the Stack for Fun and Profit) rather than the
trivial special case I've got here.)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* PASSWORDS are 8 characters plus null */
#define PASS_SZ 9

#define PASSWORD_HASH "66666666"

void change()
{
/* write something here so that the printf in main prints the value of
* 'i' as 10 */

int i = 0;
char buffer[PASS_SZ];

/*
printf("%p\n", (void*) buffer);
printf("%p\n", (void*) &i);
*/

printf("Please enter your password\n");
gets(buffer);

/*
printf("%d\n", i);
printf("%p\n", (void*) (buffer+i));
*/

/* Now "hash" the password */
do
buffer[i++] += 5;
while(i<PASS_SZ);

if(!memcmp(buffer, PASSWORD_HASH, strlen(PASSWORD_HASH)))
printf("Password OK\n");
else
{
printf("FAILED\n");
exit(EXIT_FAILURE);
}
}

int main(void)
{
int i=5;
/*
printf("%p\n", (void*) &i);
*/
change();
printf("%d\n",i);
return 0;
}
 
A

Alexei A. Frounze

Malcolm said:
A subroutine doesn't have any access to the caller's local variables.

However you can give it such access by passing them as pointers.

void change2(int *iptr)
{
/* do anything you wnat with the value you are passed */
printf("d", *iptr);
*iptr = 2;
}

Continuing the perversity, we can do something like this:

int *p;
void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
*p = 10;
}

int main(void)
{
int i=5;
p = &i;
change();
printf("%d\n",i);
return 0;
}

Alex
 
C

CBFalconer

Tim said:
.... snip ...

printf("Please enter your password\n");
gets(buffer);

You just got laughed out of any society based on the C language.
Never, ever, use gets. For anything.
 
N

Netocrat

You just got laughed out of any society based on the C language.
Never, ever, use gets. For anything.

But don't you think that the point of his post was to demonstrate why gets
is so dangerous?

i.e. he expressly showed us the compiler warning and headed his source:
"bad code follows".
 
R

Robert Gamble

CBFalconer said:
You just got laughed out of any society based on the C language.
Never, ever, use gets. For anything.

Let's take a look at some of what you conveniently snipped:
From the rest of the post it is obvious that Tim was using the weakness
of the gets() function to demonstrate the exact reason it shouldn't be
used by showing how such code could be exploited.

I'm assuming you just neglected to read the post before you replied (as
opposed to being dense or a troll).

Robert Gamble
 
C

CBFalconer

Robert said:
Let's take a look at some of what you conveniently snipped:
.... snip ...


I'm assuming you just neglected to read the post before you
replied (as opposed to being dense or a troll).

True. I saw a gets in passing and reacted like a Pavlovian dog.
 
K

Keith Thompson

CBFalconer said:
Robert Gamble wrote: [...]
I'm assuming you just neglected to read the post before you
replied (as opposed to being dense or a troll).

True. I saw a gets in passing and reacted like a Pavlovian dog.

They usually respond better to putchar('\a').
 
C

Chris Croughton

CBFalconer said:
Robert Gamble wrote: [...]
I'm assuming you just neglected to read the post before you
replied (as opposed to being dense or a troll).

True. I saw a gets in passing and reacted like a Pavlovian dog.

They usually respond better to putchar('\a').

I'd post that to ahbou if (a) I could remember how and (b) I thought
that anyone outside the C community would get the joke...

Chris C
 
C

cs

Hi All,

Consider the following code snippet:

------------------------------------------

#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
}
int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
------------------------------------------

apart from the trivial pre-processor trick like this:

#define printf(a,i) printf(a,2*i)

is there any way to achieve it ?

Thanks.

i think in "standard c" is not possible (nor desirable).
this seems ok for my cpu+compiler+os

#include <stdio.h>

void change()
{
/* write something here so that the printf in main prints the value of
'i' as 10 */
asm{ mov ebx, 10
pop eax
push ebx
}
}

/* compiler says that i==ebx */
int main(void)
{
int i=5;
change();
printf("%d\n",i);
return 0;
}
 
N

noblesantosh

Hi nitin,
Check it out, it works absolutely perfect.

#include <stdio.h>

void change(void)
{
/* write something here so that the printf in main prints the
value of
* 'i' as 10 */
asm(" popl %ebp ");
asm(" movl $10, -4(%ebp) ");
asm(" pushl %ebp ");

}

int main(void)
{
int i = 5;
change();
printf("%d\n", i);
return 0;
}

--santosh
 
R

Richard Heathfield

Hi nitin,
Check it out, it works absolutely perfect.

gcc -W -Wall -ansi -pedantic -O2 -g -pg -c -o foo.o foo.c
foo.c: In function `change':
foo.c:8: warning: implicit declaration of function `asm'
gcc -W -Wall -ansi -pedantic -O2 -g -pg -o foo foo.o
foo.o: In function `change':
foo.c:8: undefined reference to `asm'
foo.c:9: undefined reference to `asm'
foo.c:10: undefined reference to `asm'
collect2: ld returned 1 exit status
make: *** [foo] Error 1
 
N

noblesantosh

it works, compile it as follows,

gcc foo.c -o foo

Later try with other options and let me know what happens.
--santosh
 
N

noblesantosh

the asm keyword is not a part of the ANSI C standard. you cann't use
-ansi -pedantic with this code.
 
F

Flash Gordon

it works, compile it as follows,

gcc foo.c -o foo

Later try with other options and let me know what happens.

Please provide context so that people can see what you are replying to.
If you read this group you will find Kieth and CBFalconer regularly
providing instructions.

In any case, not it does not work:

bash-2.04$ cat t.c
#include <stdio.h>

void change(void)
{
/* write something here so that the printf in main prints the
value of
* 'i' as 10 */
asm(" popl %ebp ");
asm(" movl $10, -4(%ebp) ");
asm(" pushl %ebp ");

}

int main(void)
{
int i = 5;
change();
printf("%d\n", i);
return 0;
}
bash-2.04$ gcc t.c -o t
Assembler:
/tmp//ccdwnHom.s: line 21: 1252-142 Syntax error.
/tmp//ccdwnHom.s: line 22: 1252-016 The specified opcode or pseudo-op is
not valid.
Use supported instructions or pseudo-ops only.
/tmp//ccdwnHom.s: line 22: 1252-142 Syntax error.
/tmp//ccdwnHom.s: line 23: 1252-142 Syntax error.
bash-2.04$

The point is that asm (as used in your program) is an extension and not
part fo the C language, and it is not portable even amongst the systems
that have it.
 
R

Richard Heathfield

the asm keyword is not a part of the ANSI C standard.
Precisely.

you cann't use
-ansi -pedantic with this code.

You have that exactly the wrong way around.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,166
Messages
2,570,907
Members
47,448
Latest member
DeanaQ4445

Latest Threads

Top