Tunneling IP data using ICMP packets
ICMP packets are used to encapsulate IP datagrams. This IP datagram may be: a UDP packet, part of a TCP segment, part of an SCTP/GRE/MPLS protocol data unit,or any other protocol higher than layer 2.
Tunneling TCP data via ICMP
ICMP packets are used to encapsulate TCP segments, or IP datagrams that consist only of TCP segments.
An ICMP echo request allows the sender to specify a payload. A "hack" of ICMP could, for example, exploit this fact and put a TCP packet in the payload. Something on the receiving end would have to know this and play the game as well. If you get creative with the other ICMP request types you probably could do a lot.
A great example of twisting a protocol towards a use it wasn't intended is
iodine (http://code.kryo.se/iodine/) which tunnels IP over DNS requests.
(Side note: note that there is a "protocol field" in the IP header that identifies what upper layer protocol is being transported. TCP is protocol #6, GRE is protocol #47, etc. (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml))